Page MenuHomec4science

No OneTemporary

File Metadata

Created
Thu, Oct 3, 06:33
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.clang-tidy b/.clang-tidy
index a1c6f4e86..c20bc84eb 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,30 +1,35 @@
Checks: "
-*,
modernize-use-*,
-modernize-use-trailing-return-type*,
cppcoreguidelines-*,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
+ -cppcoreguidelines-non-private-member-variables-in-classes,
+ -cppcoreguidelines-avoid-const-or-ref-data-members,
+ -cppcoreguidelines-avoid-do-while,
+ -cppcoreguidelines-avoid-magic-numbers,
+ -cppcoreguidelines-missing-std-forward,
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/.gitignore b/.gitignore
index 050156e04..e41e73f24 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,35 +1,37 @@
_skbuild
-build*
+build*/
.dir-locals.el
TAGS
third-party/*/
!third-party/cmake/*
!third-party/akantu_iterators
!third-party/iohelper
+doc/dev-doc/auto_examples/*
+doc/dev-doc/examples/*
*~
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/templates.yaml b/.gitlab-ci.d/templates.yaml
deleted file mode 100644
index 902993507..000000000
--- a/.gitlab-ci.d/templates.yaml
+++ /dev/null
@@ -1,169 +0,0 @@
-# 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_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:
- - 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/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:
- - 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:
- - 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)
- artifacts:
- when: on_success
- paths:
- - 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;
- - 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
- - 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 2f0fd22c9..ac305bf70 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,412 +1,431 @@
# yaml-language-server: $schema=gitlab-ci
# yaml-language-server: $format.enable=false
stages:
- version
- configure
- build_libs
- build_tests
- test
- code_quality
- deploy
+workflow:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ - if: $CI_COMMIT_TAG =~ /^v[0-9].*$/
+
include:
- local: ".gitlab-ci.d/*.yaml"
+ local: ".gitlab/ci.d/*.yaml"
#-------------------------------------------------------------------------------
# Rebuilding the docker images if needed
#-------------------------------------------------------------------------------
docker build:debian-bullseye:
variables:
- IMAGE_NAME: debian:bullseye
+ IMAGE_NAME: 'debian:bullseye'
extends: .docker_build
docker build:ubuntu-lts:
variables:
- IMAGE_NAME: ubuntu:lts
+ IMAGE_NAME: 'ubuntu:lts'
extends: .docker_build
docker build:manylinux:
variables:
- IMAGE_NAME: manylinux:2014_x86_64
+ 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
- .configure
needs:
- version_determination
build_libs:debian_bullseye_gcc:
extends:
- .debian_bullseye_gcc
- .build_coverage
- .build_libs
needs:
- job: configure:debian_bullseye_gcc
build_tests:debian_bullseye_gcc:
extends:
- .debian_bullseye_gcc
- .build_coverage
- .build_tests
needs:
- job: build_libs:debian_bullseye_gcc
test:debian_bullseye_gcc:
extends:
- .debian_bullseye_gcc
- .build_coverage
- .tests
coverage: '/^lines: (\d+\.\d+\%)/'
needs:
- job: build_tests:debian_bullseye_gcc
# ------------------------------------------------------------------------------
# Debian bullseye compiled with Clang
# ------------------------------------------------------------------------------
configure:debian_bullseye_clang:
extends:
- .debian_bullseye_clang
- .build_release
- .configure
needs:
- version_determination
build_libs:debian_bullseye_clang:
extends:
- .debian_bullseye_clang
- .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_release
- .tests
coverage: '/^lines: (\d+\.\d+\%)/'
needs:
- 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_libs:ubuntu_lts_gcc:
extends:
- .ubuntu_lts_gcc
- .build_release
- .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_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_libs:ubuntu_lts_gcc_valgrind:
extends:
- .ubuntu_lts_gcc
- .build_valgrind
- .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_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} ..
+ - .manylinux_2014_x86_64_gcc
+ - .configure_python
needs:
- version_determination
- artifacts:
- when: on_success
- paths:
- - 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
+ - .build_python_akantu
+ - .manylinux_2014_x86_64_gcc
needs:
- job: configure:python_package
build_pip:python_package:
- stage: build_tests
extends:
+ - .code_only
- .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
+ - .manylinux_2014_x86_64_gcc
+ - .build_python_package
needs:
- job: build_akantu:python_package
- artifacts:
- when: on_success
- paths:
- - wheelhouse
- expire_in: 10h
test:python_package:
- stage: test
+ extends:
+ - .test_python_package
+ - .code_only
image: python:3.10
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/
+ before_script:
- apt update && apt install -y gmsh
- - gmsh -2 bar.geo
- - python ./dynamics.py
+# ------------------------------------------------------------------------------
+# MacOS X to build python packages
+# ------------------------------------------------------------------------------
+configure:python_package_macos:
+ extends:
+ - .configure_python
+ - .macos_clang
+ needs:
+ - version_determination
+
+build_akantu:python_package_macos:
+ extends:
+ - .build_python_akantu
+ - .macos_clang
+ needs:
+ - job: configure:python_package_macos
+
+build_pip:python_package_macos:
+ extends:
+ - .build_python_package
+ - .macos_clang
+ needs:
+ - job: build_akantu:python_package_macos
+
+test:python_package_macos:
+ extends:
+ - .test_python_package
+ - .macos_clang
+ needs:
+ - job: build_pip:python_package_macos
+
+# ------------------------------------------------------------------------------
+# PYPI Upload
+# ------------------------------------------------------------------------------
package:python_gitlab:
stage: deploy
image: python:latest
+ variables:
+ TWINE_PASSWORD: ${CI_JOB_TOKEN}
+ TWINE_USERNAME: gitlab-ci-token
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/*
+ - python3 -m twine upload --repository-url https://gitlab.com/api/v4/projects/${CI_PROJECT_ID}/packages/pypi
+ wheelhouse/*
+ wheelhouse_macos/*
needs:
- job: build_pip:python_package
- job: test:python_package
- only:
- - master
+ - job: build_pip:python_package_macos
+ - job: test:python_package_macos
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
package:python_pypi:
stage: deploy
image: python:latest
+ variables:
+ TWINE_PASSWORD: ${PYPI_TOKEN}
+ TWINE_USERNAME: __token__
script:
- pip install twine
- - TWINE_PASSWORD=${PYPI_TOKEN} TWINE_USERNAME=__token__
- python3 -m twine upload --verbose wheelhouse/*
+ - python3 -m twine upload --verbose
+ wheelhouse/*
+ wheelhouse_macos/*
needs:
- job: build_pip:python_package
- job: test:python_package
- only:
- - tags
+ - job: build_pip:python_package_macos
+ - job: test:python_package_macos
+ rules:
+ - if: $CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /v[0-9]+.*/
+
+
+# ------------------------------------------------------------------------------
+# Release
+# ------------------------------------------------------------------------------
+package:release:
+ stage: deploy
+ image: debian:testing
+ variables:
+ EXAMPLES_PACKAGE: "akantu-python-examples-${CI_COMMIT_TAG}.tgz"
+ PACKAGE_REGISTRY_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/akantu-examples/${CI_COMMIT_TAG}"
+ rules:
+ - if: $CI_COMMIT_TAG && $CI_COMMIT_TAG =~ /v[0-9]+.*/
+ script:
+ - export VERSION=$(cat VERSION)
+ - |
+ tar -cvzf akantu-python-examples-${CI_COMMIT_TAG}.tgz \
+ --exclude "CMakeFiles" \
+ --exclude "*\.cmake" \
+ --exclude "Makefile" \
+ --transform 's:^build/examples/python:akantu-python-examples:' \
+ build/examples/python
+ - |
+ curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \
+ --upload-file ${EXAMPLES_PACKAGE} ${PACKAGE_REGISTRY_URL}/${EXAMPLES_PACKAGE}
+ - export DESCRIPTION=$(markdown-extract "Version ${VERSION}" CHANGELOG.md)
+ - |
+ release-cli create \
+ --name "Version ${VERSION}" \
+ --description "${DESCRIPTION}" \
+ --tag-name "${CI_COMMIT_TAG}" \
+ --assets-link "{\"name\": \"Python Examples\", \"url\": \"${PACKAGE_REGISTRY_URL}/${EXAMPLES_PACKAGE}\", \"link_type\": \"Package\"}" \
+ --assets-link "{\"name\": \"PyPi package\", \"url\": \"https://pypi.org/project/akantu/${VERSION}/\", \"link_type\": \"Package\"}" \
+ --assets-link "{\"name\": \"Documentation\", \"url\": \"https://akantu.readthedocs.io/en/${CI_COMMIT_TAG}/\", \"link_type\": \"Other\"}"
+ needs:
+ - job: build_tests:debian_bullseye_clang
+ - job: version_determination
# ------------------------------------------------------------------------------
# Code Quality
# ------------------------------------------------------------------------------
cq:code_quality:
extends:
- .code_quality_gitlab_template
+ - .code_only
needs:
- job: build_libs:debian_bullseye_clang
artifacts:
paths:
- gl-code-quality-report.json
cq:clang_tidy:
extends:
- .clang_tools
+ - .code_only
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} > gl-clang-tidy-report.json
needs:
- job: configure:debian_bullseye_clang
artifacts:
paths:
- gl-clang-tidy-report.json
cq:clang_format:
extends:
- .clang_tools
+ - .code_only
script:
- test/ci/scripts/cq
-x third-party
-x extra-packages
-x build
clang-format
-p ${CI_PROJECT_DIR} > gl-clang-format-report.json
needs:
- job: configure:debian_bullseye_clang
artifacts:
paths:
- gl-clang-format-report.json
cq:compilation_warnings:
stage: code_quality
image: python:latest
+ extends:
+ - .code_only
script:
- pip install warning-parser termcolor Click tqdm
- 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_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
+ - .code_only
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
diff --git a/.gitlab-ci.d/code-quality.yaml b/.gitlab/ci.d/code-quality.yaml
similarity index 85%
rename from .gitlab-ci.d/code-quality.yaml
rename to .gitlab/ci.d/code-quality.yaml
index 837888511..a8cc1e262 100644
--- a/.gitlab-ci.d/code-quality.yaml
+++ b/.gitlab/ci.d/code-quality.yaml
@@ -1,70 +1,66 @@
.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.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'
+ - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
+ - git diff --name-only $CI_COMMIT_SHA $CI_MERGE_REQUEST_DIFF_BASE_SHA > file_list
+ - FILE_LIST_ARG='-f file_list'
- fi
diff --git a/.gitlab-ci.d/images.yaml b/.gitlab/ci.d/images.yaml
similarity index 84%
rename from .gitlab-ci.d/images.yaml
rename to .gitlab/ci.d/images.yaml
index e960e3df6..1ab2e0f44 100644
--- a/.gitlab-ci.d/images.yaml
+++ b/.gitlab/ci.d/images.yaml
@@ -1,112 +1,126 @@
-# 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}/*
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ changes:
+ compare_to: 'master'
+ paths:
+ - test/ci/${IMAGE_NAME}/*
+ when: manual
+ allow_failure: true
# ------------------------------------------------------------------------------
.cache_build:
variables:
CCACHE_BASEDIR: ${CI_PROJECT_DIR}/
CCACHE_DIR: ${CI_PROJECT_DIR}/.ccache
CCACHE_MAXSIZE: 1Gi
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:
+ variables:
+ IMAGE_NAME: 'manylinux:2014_x86_64'
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_ubuntu
- .image_ubuntu_lts
- .cache_build
-.manylinux_2014_x64_gcc:
+.manylinux_2014_x86_64_gcc:
variables:
- output: manylinux_2014_x64_gcc
+ output: manylinux_2014_x86_64_gcc
extends:
- .compiler_gcc
- .image_manylinux
- .cache_build
+
+.macos_clang:
+ variables:
+ IMAGE_NAME: 'macosx'
+ PLAT_SUFFIX: '_macos'
+ output: macox_clang
+ CC: /usr/bin/clang
+ CXX: /usr/bin/clang++
+ tags:
+ - macos
diff --git a/.gitlab/ci.d/templates.yaml b/.gitlab/ci.d/templates.yaml
new file mode 100644
index 000000000..22f873739
--- /dev/null
+++ b/.gitlab/ci.d/templates.yaml
@@ -0,0 +1,314 @@
+# yaml-language-server: $schema=gitlab-ci
+# yaml-language-server: $format.enable=false
+
+# Split ci
+.documentation_only:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ changes:
+ compare_to: 'master'
+ paths:
+ - doc/**/*
+ - examples/**/*
+ - .readthedocs.yaml
+ - README.md
+ - CHANGELOG.md
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_TAG
+
+.code_only:
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ changes:
+ compare_to: 'master'
+ paths:
+ - "**/*.{cc, hh, txt, cmake, py}"
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - if: $CI_COMMIT_TAG
+
+# Configuration template
+.configure:
+ stage: configure
+ extends:
+ - .code_only
+ 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_IMPLICIT_SOLVER:STRING="Mumps"
+ -DAKANTU_PARALLEL:BOOL=TRUE
+ -DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE
+ -DAKANTU_DIFFUSION: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:
+ - VERSION
+ - compile_commands.json
+ expire_in: 10h
+
+# Build the libraries
+.build_libs:
+ stage: build_libs
+ extends:
+ - .code_only
+ 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/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:
+ - VERSION
+ - build-${output}-err.log
+ - compile_commands.json
+ expire_in: 10h
+ timeout: 5h
+
+# build the tests
+.build_tests:
+ stage: build_tests
+ extends:
+ - .code_only
+ 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:
+ - 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)
+ artifacts:
+ when: on_success
+ paths:
+ - VERSION
+ - build-${output}-err.log
+ - compile_commands.json
+ - build
+ exclude:
+ - build/**/*.o
+ expire_in: 10h
+
+# Run the tests
+.tests:
+ stage: test
+ extends:
+ - .code_only
+ 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;
+ - 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
+ - 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
+
+# ------------------------------------------------------------------------------
+# Python stuffs
+# ------------------------------------------------------------------------------
+.configure_python:
+ stage: configure
+ extends:
+ - .build_release
+ cache:
+ - key: ${output}-${BUILD_TYPE}-ccache
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ paths:
+ - build/
+ - spack/
+ script:
+ # Variables for cmake
+ - source test/ci/${IMAGE_NAME}/configure_env.sh
+
+ # create the build folder
+ - cmake -E make_directory build
+ - cd build
+
+ # Configure in sequential and without tests or examples
+ - cmake -DAKANTU_COHESIVE_ELEMENT:BOOL=TRUE
+ -DAKANTU_IMPLICIT:BOOL=TRUE
+ -DAKANTU_IMPLICIT_SOLVER:STRING=Eigen
+ -DAKANTU_PARALLEL:BOOL=FALSE
+ -DAKANTU_STRUCTURAL_MECHANICS:BOOL=TRUE
+ -DAKANTU_DIFFUSION: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
+ -DCMAKE_INSTALL_PREFIX:PATH=${CI_PROJECT_DIR}/install
+ -DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} ..
+ artifacts:
+ when: on_success
+ paths:
+ - VERSION
+ expire_in: 10h
+
+
+.build_python_akantu:
+ stage: build_libs
+ extends:
+ - .build_release
+ - .code_only
+ cache:
+ - key: ${output}-${BUILD_TYPE}-ccache
+ policy: pull-push
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ policy: pull-push
+ paths:
+ - build/
+ - spack/
+ script:
+ - source test/ci/${IMAGE_NAME}/build_env.sh
+
+ - cmake --build build --target akantu -j1
+ - cmake --install build
+ artifacts:
+ when: on_success
+ paths:
+ - install/
+ - VERSION
+ expire_in: 10h
+
+.build_python_package:
+ stage: build_tests
+ extends:
+ - .build_release
+ - .code_only
+ cache:
+ - key: ${output}-${BUILD_TYPE}-ccache
+ paths:
+ - .ccache/
+ - key: ${output}-${BUILD_TYPE}-build-${CI_COMMIT_SHORT_SHA}
+ policy: pull
+ paths:
+ - build/
+ - spack/
+ script:
+ - export CI_AKANTU_INSTALL_PREFIX=${CI_PROJECT_DIR}/install
+ - test/ci/${IMAGE_NAME}/make-wheels.sh
+ artifacts:
+ when: on_success
+ paths:
+ - wheelhouse${PLAT_SUFFIX}
+ expire_in: 10h
+
+.test_python_package:
+ stage: test
+ needs:
+ - job: build_pip:python_package_macos
+ script:
+ - python3 -m venv venv
+ - source venv/bin/activate
+
+ - pip install numpy scipy
+ - pip install akantu --no-index --find-links=${PWD}/wheelhouse${PLAT_SUFFIX}
+
+ - python -c "import akantu"
+
+ - cd examples/python/solid_mechanics_model/dynamics/
+ - gmsh -2 bar.geo
+ - python ./dynamics.py
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 0a4f28107..d0d4fd59b 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -1,21 +1,30 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the docs/ directory with Sphinx
sphinx:
builder: html
configuration: doc/dev-doc/conf.py
-# Optionally build your docs in additional formats such as PDF
-# formats:
-# - pdf
+build:
+ os: "ubuntu-22.04"
+ tools:
+ python: "3.11"
+ # apt_packages:
+ # - python3-breathe
+ # - python3-git
+ # - python3-jinja2
+ # - python3-myst-parser
+ # - python3-sphinx
+ # - python3-sphinx-copybutton
+ # - python3-sphinx-rtd-theme
+ # - python3-sphinxcontrib.bibtex
+ # - python3-urllib3
-# Optionally set the version of Python and requirements required to build your docs
python:
- version: 3.7
install:
- requirements: doc/dev-doc/requirements.txt
diff --git a/CHANGELOG.md b/CHANGELOG.md
deleted file mode 100644
index db355d6a0..000000000
--- a/CHANGELOG.md
+++ /dev/null
@@ -1,155 +0,0 @@
-## Version 5.0.2 (06-30-2023)
-
-### Added
-
-- pypi package for python 3.11 and 3.12
-
-## Version 5.0.1 (05-05-2023)
-
-### Changed
-
-- Bug fixes:
- - bad constcorectness in arrays
- - applyBC broken
-
-- Extending python API
-
-## Version 5.0 (03-28-2023)
-
-### Changed
-
-- C++ standard 17 is now accepted
-- `Vector<T>` and `Matrix<T>` changed from internal types to Eigen::Matrix<T>
-- `VectorProxy<T>` and `MatrixProxy<T>` are now `Eigen::Map<Eigen::Matrix<T>>`
- This introduces a potential bug if codes like the following example where used:
- ```
- for(auto && v_ : make_view(vectors, dim)) {
- Vector<Real> v(v_);
- ...
- }
- ```
- With the new version the temporary vector `v` will be a deep copy of `v_`
- instead of a shallow copy as in the previous version
-
-### Added
-
-- `make_view` as a static dimension version for vectors and matrices
- `make_view<size>(vectors)` and `make_view<rows, cols>(matrices)`
-- `zip` iterators can be named, in which case the
- return tuple is a `named_tuple`.
- ```
- for(auto && t : zip("a"_n = as, "b"_n = bs)) {
- auto && a = t["a"_n];
- auto && b = t["b"_n];
- ...
- }
- ```
-
-### Deprecated
-
-- `begin_reinterpret` and `end_reinterpret` are error prone and deprecated in favor of `make_view`
-- `storage()` members are deprecated in favor of `data()` in order to be compatible with the STL
-- `get(.*)Energy(ElementType type, Idx index)` are deprecated in favor of `get(.*)Energy(const Element & element)`
- elements can be implicitly created, `getEnergy({type, index, _not_ghost})`
-- `begin_(node|element)_group` and `end_(node|element)_group` are replaced by `iterate(Node|Element)Groups`
-- In the python interface:
- - the global `setDebugLevel`, `getDebugLevel` and `printBacktrace` were moved in the sub-module `debug`
- - the call to `finalize` is not needed
- - `applyDirichketBC` was replaced by `applyBC`
-
-### Deleted
-
-- `getForce`, `firstType()`, `lastType()` that where deprecated in version 4.0
-
-
-## 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 more 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 (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/CHANGELOG.md b/CHANGELOG.md
new file mode 120000
index 000000000..1d9946903
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1 @@
+doc/dev-doc/changelog.md
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca11f0d8a..cfbd51651 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,207 +1,211 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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.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)
set(ENV{RUNNING_IN_CMAKE} True) # Used by sphinx but could be used by any script
#===============================================================================
# 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)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
+ file(GLOB_RECURSE AKANTU_EXAMPLES_DOC_SRCS CONFIGURE_DEPENDS "examples/*.rst")
+ else()
+ file(GLOB_RECURSE AKANTU_EXAMPLES_DOC_SRCS "examples/*.rst")
+ endif()
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/README.md b/README.md
index 4502c9869..9fa8e2ac3 100644
--- a/README.md
+++ b/README.md
@@ -1,159 +1,158 @@
# `Akantu`: Swiss-Made Open-Source Finite-Element Library
[![joss](https://joss.theoj.org/papers/3abf3c7945cc9a016a946ce9e02e357f/status.svg)](https://joss.theoj.org/papers/3abf3c7945cc9a016a946ce9e02e357f) [![license](https://img.shields.io/badge/license-LGPLv3-green)](https://www.gnu.org/licenses/lgpl-3.0.en.html) [![readthedoc](https://readthedocs.org/projects/akantu/badge/?version=master)](https://akantu.readthedocs.io/en/latest/?badge=master)
`Akantu` means a little element in Kinyarwanda, a Bantu language. From now on it
is also an open-source object-oriented library which has the ambition to be
generic and efficient. Even though the code is written to be generic, Akantu
strength are in solid mechanics models for fracture and contact simulations.
The full documentation can be found on [ReadTheDocs](https://akantu.readthedocs.io/en/latest/)
# 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 (pre-processor and Spirit)
- - zlib
- Eigen3 (if not present the build system will try to download it)
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)
### On `.deb` based systems
``` sh
- > sudo apt install cmake libboost-dev zlib1g-dev gmsh libeigen3-dev
+ > sudo apt install cmake libboost-dev gmsh libeigen3-dev
# For parallel
> sudo apt install mpi-default-dev libmumps-dev libscotch-dev
# For sequential
> sudo apt install libmumps-seq-dev
```
### Using `conda`
This works only for sequential computation since `mumps` from conda-forge is compiled without MPI support
``` sh
> conda create -n akantu
> conda activate akantu
> conda install boost cmake
> conda install -c conda-forge mumps
```
### Using `homebrew`
``` sh
> brew install gcc
> brew install boost@1.76
> brew tap brewsci/num
> brew install brewsci-mumps --without-brewsci-parmetis
```
If it does not work you can edit url to http://graal.ens-lyon.fr/MUMPS/MUMPS_5.3.5.tar.gz using the command:
``` sh
> brew edit brewsci/num
```
## Configuring and compilation
`Akantu` is a [CMake](https://cmake.org/) project, so to configure it, you can follow the usual way:
``` sh
> cd akantu
> mkdir build
> cd build
> ccmake ..
[ Set the options that you need ]
> make
> make install
```
### On Mac OS X with `homebrew`
You will need to specify the compiler explicitly:
``` sh
> CC=gcc-12 CXX=g++-12 FC=gfortran-12 cmake ..
```
Considering the homebrew is installed in `/opt/homebrew`
Define the location of the ``Scotch`` library path:
``` sh
> cmake .. -DSCOTCH_LIBRARY="/opt/homebrew/lib/libscotch.dylib;/opt/homebrew/lib/libscotcherr.dylib;/opt/homebrew/lib/libscotcherrexit.dylib"
```
Specify path to all ``MUMPS`` libraries:
``` sh
> cmake .. -DMUMPS_DIR=/opt/homebrew/opt/brewsci-mumps
```
In case the above does not work, specify the ``MUMPS`` path manually using (e.g.):
``` sh
> cmake .. -DMUMPS_LIBRARY_COMMON=/opt/homebrew/opt/brewsci-mumps/lib/libmumps_common.dylib
```
If compilation does not work change the path of the failing libraries to brew downloads in `/opt/homebrew/`.
## Using the python interface
You can install ``Akantu`` using pip, this will install a pre-compiled version, this works only on Linux machines for now:
``` sh
> pip install akantu
```
You can then import the package in a python script as:
``` python
import akantu
```
The python API is similar to the C++ one. If you
encounter 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).
# Contributing
## Contributing new features, bug fixes
Any contribution is welcome, we are trying to follow a [gitflow](https://nvie.com/posts/a-successful-git-branching-model/) workflow, so the project `developers` can create branches named `features/<name of my feature>` or `bugfixes/<name of the fix>` directly in the main `akantu` repository.
External fellows can [Fork](https://gitlab.com/akantu/akantu/-/forks/new) the project.
In both cases the modifications have to be submitted in the form of a [Merge Request](https://gitlab.com/akantu/akantu/-/merge_requests/new).
## Asking for help, reporting issues
If you want to ask for help concerning Akantu's compilation, usage or problem with the code do not hesitate to open an [Issue](https://gitlab.com/akantu/akantu/-/issues/new) on gitlab. If you want to contribute and don't know where to start, you are also invited to open an issue.
# Tutorials with the python interface
To help getting started, multiple tutorials using the python interface are
available as notebooks with pre-installed version of `Akantu` on Renku. The tutorials can be tested here:
[![renku](https://user-content.gitlab-static.net/52a4794df1236b248c8fc870bd74e9d787c0e2cb/68747470733a2f2f72656e6b756c61622e696f2f72656e6b752d62616467652e737667)](https://renkulab.io/projects/guillaume.anciaux/akantu-tutorials/sessions/new?autostart=1)
diff --git a/cmake/AkantuConfig.cmake.in b/cmake/AkantuConfig.cmake.in
index d90829b65..a228a674e 100644
--- a/cmake/AkantuConfig.cmake.in
+++ b/cmake/AkantuConfig.cmake.in
@@ -1,71 +1,75 @@
#===============================================================================
# @file AkantuConfig.cmake.in
#
# @author Nicolas Richart <nicolas.richart@epfl.ch>
#
# @date creation: Thu Dec 01 2011
# @date last modification: Mon Jan 18 2016
#
# @brief CMake file for the library
#
# @section LICENSE
#
# Copyright (©) 2010-2012, 2014, 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/>.
#
#===============================================================================
set(AKANTU_VERSION @AKANTU_SEMVER@)
@PACKAGE_INIT@
# Compute paths
get_filename_component(AKANTU_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
set(AKANTU_USE_FILE "${AKANTU_CMAKE_DIR}/AkantuUse.cmake")
include(${AKANTU_USE_FILE})
if(EXISTS "${AKANTU_CMAKE_DIR}/CMakeCache.txt")
# In build tree
include("${AKANTU_CMAKE_DIR}/AkantuBuildTreeSettings.cmake")
include(AkantuSimulationMacros)
else()
# In install tree
set(AKANTU_INCLUDE_DIRS "@CMAKE_INSTALL_PREFIX@/include/akantu")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${AKANTU_CMAKE_DIR}")
include(AkantuSimulationMacros)
endif()
-find_package(Eigen3 REQUIRED QUIET)
+set(AKANTU_DEPENDENCIES_TO_IMPORT @AKANTU_TARGETS_TO_IMPORT@)
+include(CMakeFindDependencyMacro)
+foreach(_pkg ${AKANTU_DEPENDENCIES_TO_IMPORT})
+ find_dependency(${_pkg})
+endforeach()
# Akantu exported targets
include("${AKANTU_CMAKE_DIR}/AkantuTargets.cmake")
# Dependencies
include("${AKANTU_CMAKE_DIR}/AkantuConfigInclude.cmake")
set(AKANTU_BUILD_TYPE @CMAKE_BUILD_TYPE@)
# find_akantu_dependencies()
set(AKANTU_LIBRARY akantu)
set(_akantu_libraries ${AKANTU_LIBRARIES})
list(APPEND _akantu_libraries ${AKANTU_LIBRARY} ${AKANTU_EXTRA_LIBRARIES})
list(APPEND AKANTU_INCLUDE_DIRS ${AKANTU_EXTRA_INCLUDE_DIR})
set(AKANTU_LIBRARIES ${_akantu_libraries} CACHE INTERNAL "List of akantu necessary libraries" FORCE)
check_required_components(Akantu)
diff --git a/cmake/AkantuExampleMacros.cmake b/cmake/AkantuExampleMacros.cmake
index 52968dbd1..2b3498be5 100644
--- a/cmake/AkantuExampleMacros.cmake
+++ b/cmake/AkantuExampleMacros.cmake
@@ -1,144 +1,144 @@
#===============================================================================
# Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
include(AkantuSimulationMacros)
set(AKANTU_DRIVER_SCRIPT ${AKANTU_CMAKE_DIR}/akantu_test_driver.sh)
# ==============================================================================
function(register_example example_name)
_add_akantu_simulation(${example_name} ${ARGN} LIST_FILES _example_files)
if(DEFINED _add_examples_pkg)
package_add_to_variable(EXAMPLES_FILES ${_add_examples_pkg} ${_example_files})
endif()
if(AKANTU_TEST_EXAMPLES)
cmake_parse_arguments(_example
"PYTHON;PARALLEL"
"FILES_TO_COPY;DEPENDS"
"SCRIPT"
${ARGN}
)
if(_example_FILES_TO_COPY)
foreach(_file ${_example_FILES_TO_COPY})
_add_file_to_copy(${example_name} "${_file}")
endforeach()
endif()
if(_example_PARALLEL)
set(_exe ${MPIEXEC})
if(NOT _exe)
set(_exe ${MPIEXEC_EXECUTABLE})
endif()
set(_parallel_runner -p "${_exe} ${MPIEXEC_PREFLAGS} ${MPIEXEC_NUMPROC_FLAG}" -N "2")
endif()
if(NOT _example_SCRIPT)
add_test(NAME ${example_name}-test
COMMAND ${AKANTU_DRIVER_SCRIPT}
${_parallel_runner}
-n "${example_name}-test"
-w "${CMAKE_CURRENT_BINARY_DIR}"
-e $<TARGET_FILE:${example_name}>)
elseif(_example_SCRIPT)
_add_file_to_copy(${example_name} "${_example_SCRIPT}")
if(_example_PYTHON)
add_test(NAME ${example_name}-test
COMMAND ${AKANTU_DRIVER_SCRIPT}
${_parallel_runner}
-n "${example_name}-test"
-E "${PROJECT_BINARY_DIR}/akantu_environement.sh"
-w "${CMAKE_CURRENT_BINARY_DIR}"
-e "${PYTHON_EXECUTABLE}" "${_example_SCRIPT}")
else()
add_test(NAME ${example_name}-test
COMMAND ${AKANTU_DRIVER_SCRIPT}
${_parallel_runner}
-n "${example_name}-test"
-w "${CMAKE_CURRENT_BINARY_DIR}"
-e "${_example_SCRIPT}")
endif()
endif()
endif()
endfunction()
# ==============================================================================
function(add_example et_name desc)
string(TOUPPER ${et_name} upper_name)
if(NOT _build_all_ex)
- option(AKANTU_BUILD_ALL_EXAMPLES "Activate all examples" OFF)
+ option(AKANTU_BUILD_ALL_EXAMPLES "Activate all examples" ON)
set( _build_all_ex TRUE)
endif()
option(AKANTU_BUILD_EXAMPLES_${upper_name} ${desc} OFF)
if(AKANTU_BUILD_ALL_EXAMPLES)
mark_as_advanced(FORCE AKANTU_BUILD_EXAMPLES_${upper_name})
else()
mark_as_advanced(CLEAR AKANTU_BUILD_EXAMPLES_${upper_name})
endif()
if(AKANTU_BUILD_EXAMPLES_${upper_name} OR AKANTU_BUILD_ALL_EXAMPLES)
if(NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${et_name})
message(FATAL_ERROR "The folder ${CMAKE_CURRENT_SOURCE_DIR}/${et_name} "
"that you try to register as an example sub-folder, does not exists.")
endif()
cmake_parse_arguments(_manage_example
""
""
"PACKAGE"
${ARGN}
)
if(_manage_example_PACKAGE)
set(_act TRUE)
foreach(_pkg ${_manage_example_PACKAGE})
package_is_activated(${_pkg} _activated)
if(NOT _activated)
set(_act FALSE)
endif()
endforeach()
else()
message(SEND_ERROR "Examples should be associated to a package")
endif()
if(_act)
if(DEFINED _add_examples_pkg)
set(_save_add_examples_pkg ${_add_examples_pkg})
endif()
list(GET _manage_example_PACKAGE 0 _pkg)
set(_add_examples_pkg ${_pkg})
add_subdirectory(${et_name})
unset(_add_examples_pkg)
if(DEFINED _save_add_examples_pkg)
set(_add_examples_pkg ${_save_add_examples_pkg})
unset(_save_add_examples_pkg)
endif()
endif()
endif()
endfunction()
diff --git a/cmake/AkantuExtraCompilationProfiles.cmake b/cmake/AkantuExtraCompilationProfiles.cmake
index bd071bd7c..528309abd 100644
--- a/cmake/AkantuExtraCompilationProfiles.cmake
+++ b/cmake/AkantuExtraCompilationProfiles.cmake
@@ -1,121 +1,121 @@
#===============================================================================
# Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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"
+ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} -g3 -ggdb3"
CACHE STRING "Flags used by the compiler during debug builds" FORCE)
- set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT} -ggdb3"
+ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT} -g3 -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 -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
+ declare_compilation_profile(SANITIZEDEBUG
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()
string(TOLOWER "${CMAKE_BUILD_TYPE}" _cmake_build_type_lower)
if (_cmake_build_type_lower MATCHES "valgrind")
find_program(VALGRIND_EXECUTABLE valgrind)
endif()
-option(AKANTU_USE_CCACHE "Use ccache if available to build akantu" OFF)
-
-if (AKANTU_USE_CCACHE)
- find_program(CCACHE_EXECUTABLE ccache)
+find_program(CCACHE_EXECUTABLE ccache)
+if(CCACHE_EXECUTABLE)
+ option(AKANTU_USE_CCACHE "Use ccache if available to build akantu" ON)
+ mark_as_advanced(AKANTU_USE_CCACHE)
+endif()
+option(AKANTU_SPLIT_DWARF "Split the debug symbols in separate DWO files" OFF)
+mark_as_advanced(AKANTU_SPLIT_DWARF)
+if (CCACHE_EXECUTABLE AND AKANTU_USE_CCACHE)
set(AKANTU_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}")
endif()
diff --git a/cmake/AkantuInstall.cmake b/cmake/AkantuInstall.cmake
index 73f6ab336..6c4eeafc7 100644
--- a/cmake/AkantuInstall.cmake
+++ b/cmake/AkantuInstall.cmake
@@ -1,152 +1,150 @@
#===============================================================================
# Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
#===============================================================================
# Config gen for external packages
#===============================================================================
configure_file(cmake/AkantuBuildTreeSettings.cmake.in
"${PROJECT_BINARY_DIR}/AkantuBuildTreeSettings.cmake" @ONLY)
file(WRITE "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" "
#===============================================================================
# @file AkantuConfigInclude.cmake
# @author Nicolas Richart <nicolas.richart@epfl.ch>
# @date Fri Jun 11 09:46:59 2010
#
# @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/>.
#
# @section DESCRIPTION
#
#===============================================================================
")
package_get_all_packages(_package_list)
foreach(_pkg_name ${_package_list})
# package_pkg_name(${_option} _pkg_name)
_package_is_activated(${_pkg_name} _acctivated)
_package_get_real_name(${_pkg_name} _real_name)
string(TOUPPER ${_real_name} _real_pkg_name)
file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" "
set(AKANTU_HAS_${_real_pkg_name} ${_acctivated})")
_package_get_libraries(${_pkg_name} _libs)
if(_libs)
file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" "
set(AKANTU_${_real_pkg_name}_LIBRARIES ${_libs})")
endif()
_package_get_include_dir(${_pkg_name} _incs)
if(_incs)
file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" "
set(AKANTU_${_real_pkg_name}_INCLUDE_DIR ${_incs})
")
endif()
_package_get_compile_flags(${_pkg_name} CXX _compile_flags)
if(_compile_flags)
file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" "
set(AKANTU_${_real_pkg_name}_COMPILE_CXX_FLAGS ${_compile_flags})
")
endif()
endforeach()
file(APPEND "${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake" "
set(AKANTU_EXTRA_CXX_FLAGS \"${AKANTU_EXTRA_CXX_FLAGS}\")
")
+package_get_all_target_to_import(AKANTU_TARGETS_TO_IMPORT)
+
# Create the AkantuConfig.cmake and AkantuConfigVersion files
get_filename_component(CONF_REL_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}" ABSOLUTE)
configure_file(cmake/AkantuConfig.cmake.in "${PROJECT_BINARY_DIR}/AkantuConfig.cmake" @ONLY)
configure_file(cmake/AkantuUse.cmake "${PROJECT_BINARY_DIR}/AkantuUse.cmake" COPYONLY)
package_is_activated(pybind11 _is_pybind11_activated)
package_is_activated(swig _is_swig_activated)
configure_file(cmake/akantu_environement.sh.in
${PROJECT_BINARY_DIR}/akantu_environement.sh @ONLY)
configure_file(cmake/akantu_environement.csh.in
${PROJECT_BINARY_DIR}/akantu_environement.csh @ONLY)
include(GNUInstallDirs)
-package_is_activated(python_interface _is_activated)
-if(_is_activated)
- find_package(PythonInterp ${AKANTU_PREFERRED_PYTHON_VERSION})
- configure_file(cmake/akantu_install_environement.sh.in
- ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.sh @ONLY)
- configure_file(cmake/akantu_install_environement.csh.in
- ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.csh @ONLY)
-
- install(FILES
- ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.sh
- ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.csh
- DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/akantu${AKANTU_VERSION})
-endif()
+configure_file(cmake/akantu_install_environement.sh.in
+ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.sh @ONLY)
+configure_file(cmake/akantu_install_environement.csh.in
+ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.csh @ONLY)
+
+install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.sh
+ ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/akantu_environement.csh
+ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/akantu${AKANTU_VERSION})
include(CMakePackageConfigHelpers)
configure_package_config_file(cmake/AkantuConfig.cmake.in
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
INSTALL_DESTINATION lib/cmake/${PROJECT_NAME}
)
write_basic_package_version_file(${PROJECT_BINARY_DIR}/AkantuConfigVersion.cmake
VERSION ${AKANTU_VERSION}
COMPATIBILITY SameMajorVersion)
# Install the export set for use with the install-tree
install(FILES
${PROJECT_SOURCE_DIR}/cmake/Modules/FindScaLAPACK.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindMETIS.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindParMETIS.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindPETSc.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindMumps.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindScotch.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindGMSH.cmake
${PROJECT_BINARY_DIR}/AkantuConfig.cmake
${PROJECT_BINARY_DIR}/AkantuConfigInclude.cmake
${PROJECT_BINARY_DIR}/AkantuConfigVersion.cmake
${PROJECT_SOURCE_DIR}/cmake/AkantuUse.cmake
${PROJECT_SOURCE_DIR}/cmake/AkantuSimulationMacros.cmake
${PROJECT_SOURCE_DIR}/cmake/Modules/FindGMSH.cmake
DESTINATION lib/cmake/${PROJECT_NAME}
COMPONENT dev)
diff --git a/cmake/AkantuMacros.cmake b/cmake/AkantuMacros.cmake
index 0fd9acf1a..d247ea81f 100644
--- a/cmake/AkantuMacros.cmake
+++ b/cmake/AkantuMacros.cmake
@@ -1,291 +1,234 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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=${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 05b766969..e632a4567 100644
--- a/cmake/AkantuNeedPybind11.cmake
+++ b/cmake/AkantuNeedPybind11.cmake
@@ -1,55 +1,59 @@
#===============================================================================
# Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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 AKANTU_NEED_PYBIND11_LOADED)
return()
endif()
set(AKANTU_NEED_PYBIND11_LOADED TRUE)
set(AKANTU_USE_SYSTEM_PYBIND11 AUTO CACHE STRING
"Should akantu compile the third-party: pybind11")
mark_as_advanced(AKANTU_USE_SYSTEM_PYBIND11)
set_property(CACHE AKANTU_USE_SYSTEM_PYBIND11 PROPERTY STRINGS ON OFF AUTO)
set(PYBIND11_PYTHON_VERSION ${AKANTU_PREFERRED_PYTHON_VERSION} CACHE INTERNAL "")
set(AKANTU_PYBIND11_VERSION 2.10.3)
if (AKANTU_USE_SYSTEM_PYBIND11 MATCHES "(ON|AUTO)")
+ if(CMAKE_VERSION VERSION_GREATER 3.27)
+ cmake_policy(SET CMP0148 OLD)
+ endif()
+
find_package(pybind11 ${AKANTU_PYBIND11_VERSION} QUIET)
else()
set(pybind11_FOUND FALSE)
endif()
mark_as_advanced(
pybind11_DIR
PYBIND11_PYTHONLIBS_OVERWRITE
)
if (NOT pybind11_FOUND)
set(PYBIND11_VERSION "v${AKANTU_PYBIND11_VERSION}")
set(PYBIND11_GIT "https://github.com/pybind/pybind11.git")
set(CMAKE_CXX_STANDARD ${AKANTU_CXX_STANDARD}) # Otherwhy pybind11 default to cxx14
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 81bbae0f8..633389a74 100644
--- a/cmake/AkantuPackagesSystem.cmake
+++ b/cmake/AkantuPackagesSystem.cmake
@@ -1,145 +1,99 @@
#===============================================================================
# Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
-
-#===============================================================================
-# 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 b1f3dc50d..532b5bd24 100644
--- a/cmake/AkantuTestsMacros.cmake
+++ b/cmake/AkantuTestsMacros.cmake
@@ -1,645 +1,654 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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_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()
+ if(AKANTU_SPLIT_DWARF)
+ target_compile_options(${test_name}
+ PRIVATE $<$<CONFIG:DEBUG>:-gsplit-dwarf> $<$<CONFIG:SANITIZEDEBUG>:-gsplit-dwarf>
+ )
+ target_link_options(${test_name}
+ PRIVATE -fuse-ld=gold $<$<CONFIG:DEBUG>:-Wl,--gdb-index> $<$<CONFIG:SANITIZEDEBUG>:-Wl,--gdb-index>
+ )
+ 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()
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}")
# 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/CMakePackagesSystem.cmake b/cmake/Modules/CMakePackagesSystem.cmake
index f6de58485..f4edf1d56 100644
--- a/cmake/Modules/CMakePackagesSystem.cmake
+++ b/cmake/Modules/CMakePackagesSystem.cmake
@@ -1,1097 +1,1106 @@
#===============================================================================
# Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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:
#CMakePackagesSystem
#-------------------
#
#This package defines multiple function to handle packages. This packages can
#be of two kinds regular ones and extra_packages (ex: in akantu the LGPL part
#is regular packages and extra packages are on Propetary license)
#
#Package are loaded with the help of the command:
#
#.. command:: package_list_packages
#
# package_list_packages(<regular_package_folder>
# [ EXTRA_PACKAGE_FOLDER <extra_package_folder> ]
# [ SOURCE_FOLDER <source_folder>]
# [ TEST_FOLDER <test_folder> ]
# [ MANUAL_FOLDER <manual_folder> ]
# )
#
# This command will look for packages name like ``<regular_package_folder>/<package>.cmake``
# OR ``<extra_package_folder>/<package>/package.cmake``
#
#A package is a cmake script that should contain at list the declaration of a
#package
#
#.. command:: package_declare
#
# package_declare(<package real name>
# [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL]
# [DESCRIPTION <description>] [DEFAULT <default_value>]
# [DEPENDS <pkg> ...]
# [BOOST_COMPONENTS <pkg> ...]
# [EXTRA_PACKAGE_OPTIONS <opt> ...]
# [COMPILE_FLAGS <lang> <flags>]
# [SYSTEM <ON|OFF|AUTO> [ <script_to_compile> ]]
# [FEATURES_PUBLIC <feature> ...]
# [FEATURES_PRIVATE <feature> ...]
# [EXCLUDE_FROM_ALL]
# )
#
#.. command:: package_declare_sources
#
# It can also declare multiple informations:
# source files:
#
# package_declare_sources(<package real name>
# <src1> <src2> ... <srcn>)
#
#.. command:: package_declare_documentation
#
# a LaTeX documentation
# package_declare_documentation(<package real name>
# <line1> <line2> ...<linen>)
#
#.. command:: package_declare_documentation_files
#
# LaTeX documentation files
# package_declare_documentation_files(<package real name>
# <file1> <file2> ... <filen>)
#
#Different function can also be retrieved from the package system by using the
#different accessors
#
#.. command:: package_get_name
# package_get_name(<pkg> <retval>)
#
#.. command:: package_get_real_name
# package_get_real_name(<pkg> <retval>)
#
#.. command:: package_get_option_name
# package_get_option_name(<pkg> <retval>)
#
#.. command:: package_use_system
# package_use_system(<pkg> <retval>)
#
#.. command:: package_get_nature
# package_get_nature(<pkg> <retval>)
#
#.. command:: package_get_description
# package_get_description(<pkg> <retval>)
#
#.. command:: package_get_filename
# package_get_filename(<pkg> <retval>)
#
#.. command:: package_get_sources_folder
# package_get_sources_folder(<pkg> <retval>)
#.. command:: package_get_tests_folder
# package_get_tests_folder(<pkg> <retval>)
#.. command:: package_get_manual_folder
# package_get_manual_folder(<pkg> <retval>)
#
#.. command:: package_get_find_package_extra_options
# package_get_find_package_extra_options(<pkg> <retval>)
#
#.. command:: package_get_compile_flags
# package_get_compile_flags(<pkg> <lang> <retval>)
#.. command:: package_set_compile_flags
# package_set_compile_flags(<pkg> <lang> <flag1> <flag2> ... <flagn>)
#
#.. command:: package_get_include_dir
# package_get_include_dir(<pkg> <retval>)
#.. command:: package_set_include_dir
# package_set_include_dir(<pkg> <inc1> <inc2> ... <incn>)
#.. command:: package_add_include_dir
# package_add_include_dir(<pkg> <inc1> <inc2> ... <incn>)
#
#.. command:: package_get_libraries
# package_get_libraries(<pkg> <retval>)
#.. command:: package_set_libraries
# package_set_libraries(<pkg> <lib1> <lib2> ... <libn>)
#
#.. command:: package_add_extra_dependency
# package_add_extra_dependency(pkg <dep1> <dep2> ... <depn>)
#.. command:: package_rm_extra_dependency
# package_rm_extra_dependency(<pkg> <dep>)
#.. command:: package_get_extra_dependencies
# package_get_extra_dependencies(<pkg> <retval>)
#
#.. command:: package_is_activated
# package_is_activated(<pkg> <retval>)
#.. command:: package_is_deactivated
# package_is_deactivated(<pkg> <retval>)
#
#.. command:: package_get_dependencies
# package_get_dependencies(<pkg> <PRIVATE|INTERFACE> <retval>)
#.. command:: package_add_dependencies
# package_add_dependencies(<pkg> <PRIVATE|INTERFACE> <dep1> <dep2> ... <depn>)
# package_remove_dependencies(<pkg> <dep1> <dep2> ... <depn>)
# package_remove_dependency(<pkg> <dep>)
#
#.. command:: package_on_enabled_script
# package_on_enabled_script(<pkg> <script>)
#
#.. command:: package_get_all_source_files
# package_get_all_source_files(<srcs> <public_headers> <private_headers>)
#.. command:: package_get_all_include_directories
# package_get_all_include_directories(<inc_dirs>)
#.. command:: package_get_all_external_informations
# package_get_all_external_informations(<include_dir> <libraries>)
#.. command:: package_get_all_definitions
# package_get_all_definitions(<definitions>)
#.. command:: package_get_all_extra_dependencies
# package_get_all_extra_dependencies(<dependencies>)
#.. command:: package_get_all_test_folders
# package_get_all_test_folders(<test_dirs>)
#.. command:: package_get_all_documentation_files
# package_get_all_documentation_files(<doc_files>)
#.. command:: package_get_all_activated_packages
# package_get_all_activated_packages(<activated_list>)
#.. command:: package_get_all_deactivated_packages
# package_get_all_deactivated_packages(<deactivated_list>)
#.. command:: package_get_all_packages
# package_get_all_packages(<packages_list>)
#.. command:: package_get_all_features_public
# package_get_all_features_public(<features>)
#.. command:: package_get_all_features_private
# package_get_all_features_private(<features>)
#
#
# .. command:: package_set_package_system_dependency
#
# package_set_package_system_dependency(<pkg> <system> <dep1>
# <dep2> ... <depn>)
#
# .. command:: package_get_package_system_dependency
#
# package_get_package_system_dependency(<pkg> <var>)
#
#
#]=======================================================================]
if (DEFINED CMAKE_PACKAGES_SYSTEM_LOADED)
return()
endif()
set(CMAKE_PACKAGES_SYSTEM_LOADED TRUE)
include(CMakeParseArguments)
#===============================================================================
# Package Management
#===============================================================================
if(__CMAKE_PACKAGES_SYSTEM)
return()
endif()
set(__CMAKE_PACKAGES_SYSTEM TRUE)
if(CMAKE_VERSION VERSION_GREATER 3.1.2)
cmake_policy(SET CMP0054 NEW)
endif()
#===============================================================================
option(AUTO_MOVE_UNKNOWN_FILES
"Give to cmake the permission to move the unregistered files to the ${PROJECT_SOURCE_DIR}/tmp directory" FALSE)
mark_as_advanced(AUTO_MOVE_UNKNOWN_FILES)
include(CMakePackagesSystemGlobalFunctions)
include(CMakePackagesSystemPrivateFunctions)
# ==============================================================================
# "Public" Accessors
# ==============================================================================
# ------------------------------------------------------------------------------
# Package name
# ------------------------------------------------------------------------------
function(package_get_name pkg pkg_name)
string(TOUPPER ${PROJECT_NAME} _project)
string(REPLACE "-" "_" _str_pkg "${pkg}")
string(TOUPPER ${_str_pkg} _u_package)
set(${pkg_name} ${_project}_PKG_${_u_package} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Real name
# ------------------------------------------------------------------------------
function(package_get_real_name pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_real_name(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Option name
# ------------------------------------------------------------------------------
function(package_get_option_name pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_option_name(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Set if system package or compile external lib
# ------------------------------------------------------------------------------
function(package_use_system pkg ret)
package_get_name(${pkg} _pkg_name)
_package_use_system(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_add_third_party_script_variable pkg var)
package_get_name(${pkg} _pkg_name)
_package_add_third_party_script_variable(${_pkg_name} ${var} ${ARGN})
set(${var} ${ARGN} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Add package's targets to the export list
# ------------------------------------------------------------------------------
function(package_add_to_export_list pkg)
package_get_name(${pkg} _pkg_name)
_package_add_to_export_list(${_pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Removes packages's targets from export list
# ------------------------------------------------------------------------------
function(package_remove_from_export_list pkg)
package_get_name(${pkg} _pkg_name)
_package_remove_from_export_list(${_pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Nature
# ------------------------------------------------------------------------------
function(package_get_nature pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_nature(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Description
# ------------------------------------------------------------------------------
function(package_get_description pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_description(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Package file name
# ------------------------------------------------------------------------------
function(package_get_filename pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_filename(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Source files
# ------------------------------------------------------------------------------
function(package_get_source_files pkg ret_srcs ret_pub ret_priv)
package_get_name(${pkg} _pkg_name)
_package_get_source_files(${_pkg_name} _tmp_srcs _tmp_pub _tmp_priv)
set(${ret_srcs} ${_tmp_srcs} PARENT_SCOPE)
set(${ret_pub} ${_tmp_pub} PARENT_SCOPE)
set(${ret_priv} ${_tmp_pric} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Source folder
# ------------------------------------------------------------------------------
function(package_get_sources_folder pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_sources_folder(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Test folder
# ------------------------------------------------------------------------------
function(package_get_tests_folder pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_tests_folder(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Manual folder
# ------------------------------------------------------------------------------
function(package_get_manual_folder pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_manual_folder(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Extra option for the find_package
# ------------------------------------------------------------------------------
function(package_get_find_package_extra_options pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_find_package_extra_options(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_set_find_package_extra_options pkg)
package_get_name(${pkg} _pkg_name)
_package_set_find_package_extra_options(${_pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Compilation flags
# ------------------------------------------------------------------------------
function(package_get_compile_flags pkg lang ret)
package_get_name(${pkg} _pkg_name)
_package_get_compile_flags(${_pkg_name} ${lang} _tmp)
set(${ret} "${_tmp}" PARENT_SCOPE)
endfunction()
function(package_set_compile_flags pkg lang)
package_get_name(${pkg} _pkg_name)
_package_set_compile_flags(${_pkg_name} ${lang} ${ARGN})
endfunction()
function(package_unset_compile_flags pkg lang)
package_get_name(${pkg} _pkg_name)
_package_unset_compile_flags(${_pkg_name} ${lang})
endfunction()
# ------------------------------------------------------------------------------
# Include dir
# ------------------------------------------------------------------------------
function(package_get_include_dir pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_include_dir(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_set_include_dir pkg)
package_get_name(${pkg} _pkg_name)
_package_set_include_dir(${_pkg_name} ${ARGN})
endfunction()
function(package_add_include_dir pkg)
package_get_name(${pkg} _pkg_name)
_package_add_include_dir(${_pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Libraries
# ------------------------------------------------------------------------------
function(package_get_libraries pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_libraries(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_set_libraries pkg)
package_get_name(${pkg} _pkg_name)
_package_set_libraries(${_pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Extra dependencies like custom commands of ExternalProject
# ------------------------------------------------------------------------------
function(package_add_extra_dependency pkg)
package_get_name(${pkg} _pkg_name)
_package_add_extra_dependency(${_pkg_name} ${ARGN})
endfunction()
function(package_rm_extra_dependency pkg dep)
package_get_name(${pkg} _pkg_name)
_package_rm_extra_dependency(${_pkg_name} ${dep})
endfunction()
function(package_get_extra_dependencies pkg ret)
package_get_name(${pkg} _pkg_name)
_package_get_extra_dependencies(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Activate/deactivate
# ------------------------------------------------------------------------------
function(package_is_activated pkg ret)
package_get_name(${pkg} _pkg_name)
_package_is_activated(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_is_deactivated pkg ret)
package_get_name(${pkg} _pkg_name)
_package_is_deactivated(${_pkg_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Direct dependencies
# ------------------------------------------------------------------------------
function(package_get_dependencies pkg type ret)
package_get_name(${pkg} _pkg_name)
_package_get_dependencies(${_pkg_name} ${type} _tmp_name)
_package_get_real_name(${_tmp_name} _tmp)
set(${ret} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_add_dependencies pkg type)
package_get_name(${pkg} _pkg_name)
foreach(_dep ${ARGN})
package_get_name(${_dep} _dep_pkg_name)
list(APPEND _tmp_deps ${_dep_pkg_name})
endforeach()
_package_add_dependencies(${_pkg_name} ${type} ${_tmp_deps})
endfunction()
function(package_remove_dependencies pkg type)
foreach(_dep ${ARGN})
package_remove_dependency(${pkg} _dep)
endforeach()
endfunction()
function(package_remove_dependency pkg dep)
package_get_name(${pkg} _pkg_name)
package_get_name(${dep} _dep_pkg_name)
_package_remove_dependency(${_pkg_name} PRIVATE ${_dep_pkg_name})
_package_remove_dependency(${_pkg_name} INTERFACE ${_dep_pkg_name})
endfunction()
# ------------------------------------------------------------------------------
# Documentation related functions
# ------------------------------------------------------------------------------
function(package_declare_documentation pkg)
package_get_name(${pkg} _pkg_name)
_package_set_documentation(${_pkg_name} ${ARGN})
endfunction()
function(package_declare_documentation_files pkg)
package_get_name(${pkg} _pkg_name)
_package_set_documentation_files(${_pkg_name} ${ARGN})
endfunction()
# ------------------------------------------------------------------------------
# Set any user variables needed
# ------------------------------------------------------------------------------
function(package_set_variable variable pkg)
package_get_name(${pkg} _pkg_name)
_package_set_variable(${variable} ${_pkg_name} ${ARGN})
endfunction()
function(package_add_to_variable variable pkg)
package_get_name(${pkg} _pkg_name)
_package_add_to_variable(${variable} ${_pkg_name} ${ARGN})
endfunction()
function(package_get_variable variable pkg value)
package_get_name(${pkg} _pkg_name)
_package_get_variable(${variable} ${_pkg_name} _value_tmp)
if(_value_tmp)
set(${value} ${_value_tmp} PARENT_SCOPE)
else()
unset(${value} PARENT_SCOPE)
endif()
endfunction()
# ------------------------------------------------------------------------------
# Exteral package system as apt rpm dependencies
# ------------------------------------------------------------------------------
function(package_set_package_system_dependency pkg system)
package_get_name(${pkg} _pkg_name)
_package_set_package_system_dependency(${_pkg_name} ${system} ${ARGN})
endfunction()
function(package_get_package_system_dependency pkg system var)
package_get_name(${pkg} _pkg_name)
_package_set_package_system_dependency(${_pkg_name} ${sytem} _tmp)
set(${var} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# ==============================================================================
# Global accessors
# ==============================================================================
# ------------------------------------------------------------------------------
# get the list of source files
# ------------------------------------------------------------------------------
function(package_get_all_source_files SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
string(TOUPPER ${PROJECT_NAME} _project)
unset(_tmp_srcs)
unset(_tmp_public_headers)
unset(_tmp_private_headers)
package_get_all_activated_packages(_activated_list)
foreach(_pkg_name ${_activated_list})
_package_get_source_files(${_pkg_name}
_pkg_srcs
_pkg_public_headers
_pkg_private_headers
)
list(APPEND _tmp_srcs ${_pkg_srcs})
list(APPEND _tmp_public_headers ${_pkg_public_headers})
list(APPEND _tmp_private_headers ${_pkg_private_headers})
endforeach()
set(${SRCS} ${_tmp_srcs} PARENT_SCOPE)
set(${PUBLIC_HEADERS} ${_tmp_public_headers} PARENT_SCOPE)
set(${PRIVATE_HEADERS} ${_tmp_private_headers} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get include directories
# ------------------------------------------------------------------------------
function(package_get_all_include_directories inc_dirs)
set(_tmp)
package_get_all_activated_packages(_activated_list)
foreach(_pkg_name ${_activated_list})
foreach(_type SRCS PUBLIC_HEADERS PRIVATE_HEADERS)
foreach(_file ${${_pkg_name}_${_type}})
get_filename_component(_path "${_file}" PATH)
list(APPEND _tmp "${_path}")
endforeach()
endforeach()
endforeach()
if(_tmp)
list(REMOVE_DUPLICATES _tmp)
endif()
set(${inc_dirs} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get external libraries informations
# ------------------------------------------------------------------------------
function(package_get_all_external_informations)
cmake_parse_arguments(_opt "" "PRIVATE_INCLUDE;INTERFACE_INCLUDE;LIBRARIES" "" ${ARGN})
foreach(_type PRIVATE INTERFACE)
if(_opt_${_type}_INCLUDE)
_package_get_variable_for_external_dependencies(INCLUDE_DIR ${_type} tmp_INCLUDE_DIR)
foreach(_dir ${tmp_INCLUDE_DIR})
string(FIND "${_dir}" "${CMAKE_CURRENT_SOURCE_DIR}" _pos)
if(NOT _pos EQUAL -1)
list(REMOVE_ITEM tmp_INCLUDE_DIR ${_dir})
endif()
endforeach()
set(${_opt_${_type}_INCLUDE} ${tmp_INCLUDE_DIR} PARENT_SCOPE)
endif()
endforeach()
if(_opt_LIBRARIES)
_package_get_variable_for_external_dependencies(LIBRARIES PRIVATE tmp_LIBRARIES)
_package_get_variable_for_external_dependencies(LIBRARIES INTERFACE tmp_LIBRARIES_INTERFACE)
set(${_opt_LIBRARIES} ${tmp_LIBRARIES} ${tmp_LIBRARIES_INTERFACE} PARENT_SCOPE)
endif()
endfunction()
# ------------------------------------------------------------------------------
# Get export list for all activated packages
# ------------------------------------------------------------------------------
function(package_get_all_export_list export_list)
_package_get_variable_for_activated(EXPORT_LIST _tmp)
set(${export_list} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get definitions like external projects
# ------------------------------------------------------------------------------
function(package_get_all_definitions definitions)
_package_get_variable_for_activated(OPTION_NAME _tmp)
set(${definitions} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get extra dependencies like external projects
# ------------------------------------------------------------------------------
function(package_get_all_extra_dependencies deps)
_package_get_variable_for_activated(EXTRA_DEPENDENCY _tmp)
set(${deps} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get extra infos
# ------------------------------------------------------------------------------
function(package_get_all_test_folders TEST_DIRS)
_package_get_variable_for_activated(TEST_FOLDER _tmp)
set(${TEST_DIRS} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get compilation flags
# ------------------------------------------------------------------------------
function(package_get_all_compilation_flags LANG FLAGS)
_package_get_variable_for_activated(COMPILE_${LANG}_FLAGS _tmp_flags)
string(REPLACE ";" " " _flags "${_tmp_flags}")
set(${FLAGS} ${_flags} PARENT_SCOPE)
endfunction()
+# ------------------------------------------------------------------------------
+# Get export list for all activated packages
+# ------------------------------------------------------------------------------
+function(package_get_all_target_to_import targets)
+ _package_get_variable_for_activated(TARGET_TO_IMPORT _tmp)
+ set(${targets} ${_tmp} PARENT_SCOPE)
+endfunction()
+
+
# ------------------------------------------------------------------------------
# Documentation informations
# ------------------------------------------------------------------------------
function(package_get_all_documentation_files doc_files)
set(_tmp_DOC_FILES)
package_get_all_activated_packages(_activated_list)
foreach(_pkg_name ${_activated_list})
_package_get_manual_folder(${_pkg_name} _doc_dir)
_package_get_documentation_files(${_pkg_name} _doc_files)
foreach(_doc_file ${_doc_files})
list(APPEND _tmp_DOC_FILES ${_doc_dir}/${_doc_file})
endforeach()
endforeach()
if(_tmp_DOC_FILES)
list(REMOVE_DUPLICATES _tmp_DOC_FILES)
endif()
set(${doc_files} ${_tmp_DOC_FILES} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Get package systems dependencies
# ------------------------------------------------------------------------------
function(package_get_all_package_system_dependency system deps)
string(TOUPPER ${system} _u_system)
_package_get_variable_for_activated(PACKAGE_SYSTEM_${_u_system} _tmp)
set(${deps} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# List packages
# ------------------------------------------------------------------------------
function(package_get_all_activated_packages activated_list)
package_get_project_variable(ACTIVATED_PACKAGE_LIST _activated_list)
set(${activated_list} ${_activated_list} PARENT_SCOPE)
endfunction()
function(package_get_all_deactivated_packages deactivated_list)
package_get_project_variable(DEACTIVATED_PACKAGE_LIST _deactivated_list)
set(${deactivated_list} ${_deactivated_list} PARENT_SCOPE)
endfunction()
function(package_get_all_packages packages_list)
package_get_project_variable(ALL_PACKAGES_LIST _packages_list)
set(${packages_list} ${_packages_list} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# List all the needed features
# ------------------------------------------------------------------------------
function(package_get_all_features_public features)
_package_get_variable_for_activated(FEATURES_PUBLIC _tmp)
set(${features} ${_tmp} PARENT_SCOPE)
endfunction()
function(package_get_all_features_private features)
_package_get_variable_for_activated(FEATURES_PRIVATE _tmp)
set(${features} ${_tmp} PARENT_SCOPE)
endfunction()
# ------------------------------------------------------------------------------
# Callbacks
# ------------------------------------------------------------------------------
function(package_on_enabled_script pkg script)
package_get_name(${pkg} _pkg_name)
_package_on_enable_script(${_pkg_name} "${script}")
endfunction()
# ------------------------------------------------------------------------------
# list all the packages in the PACKAGE_FOLDER
# extra packages can be given with an EXTRA_PACKAGE_FOLDER
# <package_folder>/<package>.cmake
#
# Extra packages folder structure
# <extra_package_folder>/<package>/package.cmake
# /src
# /test
# /manual
#
# ------------------------------------------------------------------------------
function(package_list_packages PACKAGE_FOLDER)
cmake_parse_arguments(_opt_pkg
"NO_AUTO_COMPILE_FLAGS"
"SOURCE_FOLDER;EXTRA_PACKAGES_FOLDER;TEST_FOLDER;MANUAL_FOLDER"
""
${ARGN})
string(TOUPPER ${PROJECT_NAME} _project)
# Cleaning some states to start correctly
package_get_all_packages(_already_loaded_pkg)
foreach(_pkg_name ${_already_loaded_pkg})
_package_unset_extra_dependencies(${_pkg_name})
_package_unset_dependencies(${_pkg_name} PRIVATE)
_package_unset_dependencies(${_pkg_name} INTERFACE)
_package_unset_activated(${_pkg_name})
endforeach()
if(_opt_pkg_SOURCE_FOLDER)
set(_src_folder "${_opt_pkg_SOURCE_FOLDER}")
else()
set(_src_folder "src/")
endif()
get_filename_component(_abs_src_folder ${_src_folder} ABSOLUTE)
if(_opt_pkg_TEST_FOLDER)
set(_test_folder "${_opt_pkg_TEST_FOLDER}")
else()
set(_test_folder "test/")
endif()
if(_opt_pkg_MANUAL_FOLDER)
set(_manual_folder "${_opt_pkg_MANUAL_FOLDER}")
else()
set(_manual_folder "doc/manual")
endif()
if(_opt_pkg_NO_AUTO_COMPILE_FLAGS)
package_set_project_variable(NO_AUTO_COMPILE_FLAGS TRUE)
else()
package_set_project_variable(NO_AUTO_COMPILE_FLAGS FALSE)
endif()
get_filename_component(_abs_test_folder ${_test_folder} ABSOLUTE)
get_filename_component(_abs_manual_folder ${_manual_folder} ABSOLUTE)
# check all the packages in the <package_folder>
file(GLOB _package_list "${PACKAGE_FOLDER}/*.cmake")
set(_package_files)
foreach(_pkg ${_package_list})
get_filename_component(_basename ${_pkg} NAME)
if(NOT _basename MATCHES "^\\.#.*")
list(APPEND _package_files ${_basename})
endif()
endforeach()
if(_package_files)
list(SORT _package_files)
endif()
# check all packages
set(_packages_list_all)
foreach(_pkg_file ${_package_files})
string(REGEX REPLACE "[0-9]+_" "" _pkg_file_stripped ${_pkg_file})
string(REGEX REPLACE "\\.cmake" "" _pkg ${_pkg_file_stripped})
set(_current_src_folder "${_abs_src_folder}" CACHE INTERNAL "" FORCE)
set(_current_test_folder "${_abs_test_folder}" CACHE INTERNAL "" FORCE)
set(_current_manual_folder "${_abs_manual_folder}" CACHE INTERNAL "" FORCE)
include("${PACKAGE_FOLDER}/${_pkg_file}")
unset(_current_src_folder CACHE)
unset(_current_test_folder CACHE)
unset(_current_manual_folder CACHE)
endforeach()
# check the extra_packages if they exists
if(_opt_pkg_EXTRA_PACKAGES_FOLDER)
file(GLOB _extra_package_list RELATIVE
"${_opt_pkg_EXTRA_PACKAGES_FOLDER}" "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/*")
foreach(_pkg ${_extra_package_list})
if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake")
package_get_name(${_pkg} _pkg_name)
_package_set_filename(${_pkg_name}
"${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake")
set(_current_src_folder "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src" CACHE INTERNAL "" FORCE)
if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test")
set(_current_test_folder "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/test" CACHE INTERNAL "" FORCE)
endif()
if(EXISTS "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual")
set(_current_manual_folder "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/manual" CACHE INTERNAL "" FORCE)
endif()
list(APPEND _extra_pkg_src_folders "${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/src")
include("${_opt_pkg_EXTRA_PACKAGES_FOLDER}/${_pkg}/package.cmake")
unset(_current_src_folder CACHE)
unset(_current_test_folder CACHE)
unset(_current_manual_folder CACHE)
endif()
endforeach()
endif()
_package_build_rdependencies()
_package_load_packages()
_package_check_files_exists()
_package_check_files_registered(${_abs_src_folder} ${_extra_pkg_src_folders})
# Load boost components if boost was loaded
package_is_activated(Boost _ret)
if(_ret)
_package_load_boost_components()
endif()
endfunction()
# ------------------------------------------------------------------------------
# macro to include internal/external packages packages
# package_declare(<package real name>
# [EXTERNAL] [META] [ADVANCED] [NOT_OPTIONAL]
# [DESCRIPTION <description>] [DEFAULT <default_value>]
# [DEPENDS <pkg> ...]
# [BOOST_COMPONENTS <pkg> ...]
# [EXTRA_PACKAGE_OPTIONS <opt> ...]
# [COMPILE_FLAGS <lang> <flags>]
# [SYSTEM <bool> [ <script_to_compile> ]]
# [FEATURES_PUBLIC <feature> ...]
# [FEATURES_PRIVATE <feature> ...])
# ------------------------------------------------------------------------------
function(package_declare pkg)
package_get_name(${pkg} _pkg_name)
_package_set_real_name(${_pkg_name} ${pkg})
_package_set_filename(${_pkg_name} "${CMAKE_CURRENT_LIST_FILE}")
_package_set_sources_folder(${_pkg_name} "${_current_src_folder}")
_package_variable_unset(SRCS ${_pkg_name})
_package_variable_unset(PUBLIC_HEADERS ${_pkg_name})
_package_variable_unset(PRIVATE_HEADERS ${_pkg_name})
if(_current_test_folder)
_package_set_tests_folder(${_pkg_name} "${_current_test_folder}")
endif()
if(_current_manual_folder)
_package_set_manual_folder(${_pkg_name} "${_current_manual_folder}")
endif()
package_get_project_variable(ALL_PACKAGES_LIST _tmp_pkg_list)
list(APPEND _tmp_pkg_list ${_pkg_name})
list(REMOVE_DUPLICATES _tmp_pkg_list)
package_set_project_variable(ALL_PACKAGES_LIST ${_tmp_pkg_list})
set(_options
EXTERNAL
NOT_OPTIONAL
META
ADVANCED
EXCLUDE_FROM_ALL)
set(_one_valued_options
DEFAULT
DESCRIPTION)
set(_multi_valued_options
DEPENDS
EXTRA_PACKAGE_OPTIONS
COMPILE_FLAGS
BOOST_COMPONENTS
SYSTEM
FEATURES_PUBLIC
FEATURES_PRIVATE)
cmake_parse_arguments(_opt_pkg
"${_options}"
"${_one_valued_options}"
"${_multi_valued_options}"
${ARGN})
if(_opt_pkg_UNPARSED_ARGUMENTS)
message("You gave to many arguments while registering the package ${pkg} \"${_opt_pkg_UNPARSED_ARGUMENTS}\"")
endif()
# set the nature
if(_opt_pkg_EXTERNAL)
_package_set_nature(${_pkg_name} "external")
elseif(_opt_pkg_META)
_package_set_nature(${_pkg_name} "meta")
else()
_package_set_nature(${_pkg_name} "internal")
endif()
_package_declare_option(${_pkg_name})
# set description
if(_opt_pkg_DESCRIPTION)
_package_set_description(${_pkg_name} ${_opt_pkg_DESCRIPTION})
else()
_package_set_description(${_pkg_name} "")
endif()
_package_get_option_name(${_pkg_name} _option_name)
_package_get_description(${_pkg_name} _description)
# get the default value
if(DEFINED _opt_pkg_DEFAULT)
set(_default ${_opt_pkg_DEFAULT})
else()
if(_opt_pkg_NOT_OPTIONAL)
set(_default ON)
else()
set(_default OFF)
endif()
endif()
# set the option if needed
if(_opt_pkg_NOT_OPTIONAL)
_package_get_nature(${_pkg_name} _nature)
_package_set_nature(${_pkg_name} "${_nature}_not_optional")
set(${_option_name} ${_default} CACHE INTERNAL "${_description}" FORCE)
mark_as_advanced(${_option_name})
else()
option(${_option_name} "${_description}" ${_default})
if(_opt_pkg_ADVANCED OR _opt_pkg_EXTERNAL)
mark_as_advanced(${_option_name})
endif()
endif()
# Set the option for third-parties that can be compiled as an ExternalProject
if(DEFINED _opt_pkg_SYSTEM)
list(LENGTH _opt_pkg_SYSTEM _length)
list(GET _opt_pkg_SYSTEM 0 _bool)
_package_set_system_option(${_pkg_name} ${_bool})
if(_length GREATER 1)
list(GET _opt_pkg_SYSTEM 1 _script)
_package_set_system_script(${_pkg_name} ${_script})
endif()
endif()
# set the dependecies
if(_opt_pkg_DEPENDS)
set(_deps_types PRIVATE PUBLIC INTERFACE)
cmake_parse_arguments(_pkg_deps
""
""
"${_deps_types}"
${_opt_pkg_DEPENDS})
list(APPEND _pkg_deps_PRIVATE ${_pkg_deps_UNPARSED_ARGUMENTS})
foreach(_type ${_deps_types})
set(_depends)
foreach(_dep ${_pkg_deps_${_type}})
package_get_name(${_dep} _dep_pkg_name)
list(APPEND _depends ${_dep_pkg_name})
endforeach()
_package_add_dependencies(${_pkg_name} ${_type} ${_depends})
endforeach()
endif()
# keep the extra option for the future find package
if(_opt_pkg_EXTRA_PACKAGE_OPTIONS)
_package_set_find_package_extra_options(${_pkg_name} "${_opt_pkg_EXTRA_PACKAGE_OPTIONS}")
endif()
# register the compilation flags
if(_opt_pkg_COMPILE_FLAGS)
set(_languages C CXX Fortran)
cmake_parse_arguments(_compile_flags
"" "" "${_languages}"
${_opt_pkg_COMPILE_FLAGS}
)
# this is done to maintain backward compatibility
if(_compile_flags_UNPARSED_ARGUMENTS)
set(_compile_flags_CXX ${_compile_flags_UNPARSED_ARGUMENTS})
endif()
foreach(_lang ${_languages})
if(_compile_flags_${_lang})
_package_set_compile_flags(${_pkg_name} ${_lang} ${_compile_flags_${_lang}})
else()
_package_unset_compile_flags(${_pkg_name} ${_lang})
endif()
endforeach()
endif()
# set the boost dependencies
if(_opt_pkg_BOOST_COMPONENTS)
_package_set_boost_component_needed(${_pkg_name} "${_opt_pkg_BOOST_COMPONENTS}")
endif()
set(_variables FEATURES_PUBLIC FEATURES_PRIVATE EXCLUDE_FROM_ALL)
foreach(_variable ${_variables})
if(_opt_pkg_${_variable})
_package_set_variable(${_variable} ${_pkg_name} "${_opt_pkg_${_variable}}")
endif()
endforeach()
endfunction()
# ------------------------------------------------------------------------------
# declare the source files of a given package
#
# package_declare_sources(<package> <list of sources>
# SOURCES <source file> ...
# PUBLIC_HEADER <header file> ...
# PRIVATE_HEADER <header file> ...)
# ------------------------------------------------------------------------------
function(package_declare_sources pkg)
package_get_name(${pkg} _pkg_name)
# get 3 lists, if none of the options given try to distinguish the different lists
cmake_parse_arguments(_opt_pkg
""
""
"SOURCES;PUBLIC_HEADERS;PRIVATE_HEADERS"
${ARGN})
set(_tmp_srcs ${_opt_pkg_SOURCES})
set(_tmp_pub_hdrs ${_opt_pkg_PUBLIC_HEADER})
set(_tmp_pri_hdrs ${_opt_pkg_PRIVATE_HEADERS})
foreach(_file ${_opt_pkg_UNPARSED_ARGUMENTS})
if(${_file} MATCHES ".*inline.*\\.cc")
list(APPEND _tmp_pub_hdrs ${_file})
elseif(${_file} MATCHES ".*\\.h+")
list(APPEND _tmp_pub_hdrs ${_file})
else()
list(APPEND _tmp_srcs ${_file})
endif()
endforeach()
_package_get_sources_folder(${_pkg_name} _src_folder)
foreach(_type _srcs _pub_hdrs _pri_hdrs)
set(${_type})
foreach(_file ${_tmp${_type}})
# get the full name
set(_full_path "${_src_folder}/${_file}")
list(APPEND ${_type} "${_full_path}")
endforeach()
endforeach()
set(${_pkg_name}_SRCS "${_srcs}"
CACHE INTERNAL "List of sources files" FORCE)
set(${_pkg_name}_PUBLIC_HEADERS "${_pub_hdrs}"
CACHE INTERNAL "List of public header files" FORCE)
set(${_pkg_name}_PRIVATE_HEADERS "${_pri_hdrs}"
CACHE INTERNAL "List of private header files" FORCE)
endfunction()
# ------------------------------------------------------------------------------
diff --git a/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake b/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
index 05ba58d33..88d0c2d8e 100644
--- a/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
+++ b/cmake/Modules/CMakePackagesSystemPrivateFunctions.cmake
@@ -1,1001 +1,1008 @@
#===============================================================================
# Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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}\"" ${ARGN})
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|TRUE)")
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})
+ _package_add_libraries(${_pkg_name} Boost::${_comp})
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)
_package_set_system_option(${pkg_name} ${_activated} FORCE)
endif()
_package_use_system(${pkg_name} _use_system)
_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;TARGET" "LINK_LIBRARIES;PREFIX;FOUND;ARGS" ${_options})
if(_opt_pkg_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "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()
+ _package_variable_unset(TARGET_TO_IMPORT ${pkg_name})
+
if(_act)
set(_include_dirs)
set(_libraries)
if(_opt_pkg_TARGET)
_package_set_libraries(${pkg_name} ${_opt_pkg_TARGET})
list(APPEND _libraries ${_opt_pkg_TARGET})
+ _package_add_to_variable(TARGET_TO_IMPORT ${pkg_name} ${_real_name})
else()
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()
+
+ if(DEFINED ${_prefix}_TARGETS_TO_IMPORT)
+ _package_add_to_variable(TARGET_TO_IMPORT ${pkg_name} ${${_prefix}_TARGETS_TO_IMPORT})
+ endif()
endforeach()
endif()
if(_required STREQUAL "QUIET")
if(_libraries)
set(_msg ${_libraries})
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/FindMETIS.cmake b/cmake/Modules/FindMETIS.cmake
index ab3b49443..3ceabff76 100644
--- a/cmake/Modules/FindMETIS.cmake
+++ b/cmake/Modules/FindMETIS.cmake
@@ -1,59 +1,42 @@
#===============================================================================
# Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
find_path(METIS_INCLUDE_DIR metis.h
PATHS "${METIS_DIR}"
ENV METIS_DIR
PATH_SUFFIXES include
)
find_library(METIS_LIBRARY NAMES metis
PATHS "${METIS_DIR}"
ENV METIS_DIR
PATH_SUFFIXES lib
)
mark_as_advanced(METIS_LIBRARY METIS_INCLUDE_DIR)
#===============================================================================
include(FindPackageHandleStandardArgs)
-if(CMAKE_VERSION VERSION_GREATER 2.8.12)
- if(METIS_INCLUDE_DIR)
- file(STRINGS ${METIS_INCLUDE_DIR}/metis.h _versions
- REGEX "^#define\ +METIS_VER_(MAJOR|MINOR|SUBMINOR) .*")
- foreach(_ver ${_versions})
- string(REGEX MATCH "METIS_VER_(MAJOR|MINOR|SUBMINOR) *([0-9.]+)" _tmp "${_ver}")
- set(_metis_${CMAKE_MATCH_1} ${CMAKE_MATCH_2})
- endforeach()
- set(METIS_VERSION "${_metis_MAJOR}.${_metis_MINOR}" CACHE INTERNAL "")
- endif()
-
- find_package_handle_standard_args(METIS
- REQUIRED_VARS
- METIS_LIBRARY
- METIS_INCLUDE_DIR
- VERSION_VAR
- METIS_VERSION)
-else()
- find_package_handle_standard_args(METIS DEFAULT_MSG
- METIS_LIBRARY METIS_INCLUDE_DIR)
-endif()
+find_package_handle_standard_args(METIS
+ REQUIRED_VARS
+ METIS_LIBRARY
+ METIS_INCLUDE_DIR)
diff --git a/cmake/Modules/FindMumps.cmake b/cmake/Modules/FindMumps.cmake
index 4b724a27f..bf8332b98 100644
--- a/cmake/Modules/FindMumps.cmake
+++ b/cmake/Modules/FindMumps.cmake
@@ -1,380 +1,394 @@
#===============================================================================
# Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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)
+ set(_target_to_import Threads PARENT_SCOPE)
elseif(_pdep MATCHES "OpenMP")
find_package(OpenMP REQUIRED QUIET)
set(${_libs} OpenMP::OpenMP_C PARENT_SCOPE)
+ set(_target_to_import OpenMP 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(_targets_to_import)
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 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 omp_ GOMP_loop_end_nowait)
set(_mumps_dep_link_gfortran gfortran)
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)
+ set(ENV{LANG} C) # Trying to get the error messages in English
+
+
# 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)
+ set(_target_to_import)
mumps_add_dependency(${_pdep} _libs _incs ${_mumps_dep_comp_${_pdep}})
debug_message(" - Found: ${_pdep} (${_libs})")
+ if(_target_to_import)
+ list(APPEND _targets_to_import ${_target_to_import})
+ endif()
+
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)
+
+ if(_targets_to_import)
+ set(MUMPS_TARGETS_TO_IMPORT ${_targets_to_import} CACHE INTERNAL "" FORCE)
+ endif()
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/material_lister.cc b/cmake/material_lister.cc
deleted file mode 100644
index 1b8cc7c91..000000000
--- a/cmake/material_lister.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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_list.hh"
-
-#include <boost/preprocessor.hpp>
-#include <iostream>
-
-int main(__attribute__((unused)) int argc,
- __attribute__((unused)) char * argv[]) {
-#define PRINT_OUT_OPTIONS(r, data, i, elem) \
- << ":" << BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 0, elem))
-
-#define PRINT_OUT(r, data, elem) \
- std::cout << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(0, elem)) << ":" \
- << BOOST_PP_STRINGIZE(BOOST_PP_ARRAY_ELEM(1, elem)) BOOST_PP_IF( \
- BOOST_PP_EQUAL(3, BOOST_PP_ARRAY_SIZE(elem)), \
- BOOST_PP_SEQ_FOR_EACH_I(PRINT_OUT_OPTIONS, _, \
- BOOST_PP_ARRAY_ELEM(2, elem)), ) \
- << std::endl;
-
- BOOST_PP_SEQ_FOR_EACH(PRINT_OUT, "toto", AKANTU_MATERIAL_LIST);
-
- return 0;
-}
diff --git a/dev-requirements.txt b/dev-requirements.txt
index 6690d8e49..11a0c9d9f 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -1,5 +1,6 @@
scikit-build
pybind11
numpy
ninja
cmake
+delocate; sys_platform == 'darwin'
diff --git a/doc/dev-doc/CMakeLists.txt b/doc/dev-doc/CMakeLists.txt
index 94163b893..3994a3ad6 100644
--- a/doc/dev-doc/CMakeLists.txt
+++ b/doc/dev-doc/CMakeLists.txt
@@ -1,77 +1,79 @@
#===============================================================================
# Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
# configured documentation tools and intermediate build results
set(BINARY_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/_build")
# Sphinx cache with pickled ReST documents
set(SPHINX_CACHE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees")
# HTML output directory
set(SPHINX_HTML_DIR "${CMAKE_CURRENT_BINARY_DIR}/html")
set(SPHINX_OUTPUT "${SPHINX_HTML_DIR}/index.html")
set(SPHINX_INPUT "${CMAKE_CURRENT_BINARY_DIR}/conf.py")
# ---------------------------------------------------------------------------- #
# Sphinx #
# ---------------------------------------------------------------------------- #
find_package(Sphinx REQUIRED)
-set(SPHINX_VERBOSE_FLAG "-q")
+set(SPHINX_VERBOSE_FLAG)
if(CMAKE_VERBOSE_MAKEFILE)
- set(SPHINX_VERBOSE_FLAG)
+ set(SPHINX_VERBOSE_FLAG "-v")
endif(CMAKE_VERBOSE_MAKEFILE)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/conf.py"
"${SPHINX_INPUT}"
@ONLY)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/manual/manual-bibliography.bib"
"${CMAKE_CURRENT_BINARY_DIR}/manual/manual-bibliography.bib"
COPYONLY)
set(SPHINX_PARALLEL_FLAG)
if (SPHINX_VERSION VERSION_GREATER_EQUAL 1.7.0)
- set(SPHINX_PARALLEL_FLAG -j auto)
+ set(SPHINX_PARALLEL_FLAG -j 1)
endif()
set(_sphinx_command ${SPHINX_BUILD_EXECUTABLE}
${SPHINX_PARALLEL_FLAG}
${SPHINX_VERBOSE_FLAG} -b html
-c "${CMAKE_CURRENT_BINARY_DIR}"
-d "${SPHINX_CACHE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
"${SPHINX_HTML_DIR}"
)
-file(GLOB_RECURSE _SPHINX_SRCS
+file(GLOB_RECURSE _SPHINX_RST_SRCS
"*.rst")
+file(GLOB_RECURSE _SPHINX_MD_SRCS
+ "*.md")
add_custom_command(
OUTPUT ${SPHINX_OUTPUT}
- COMMAND ${_sphinx_command}
- DEPENDS ${SPHINX_INPUT} ${_SPHINX_SRCS}
+ COMMAND ${CMAKE_COMMAND} -E env RUNNING_IN_CMAKE=True ${_sphinx_command}
+ DEPENDS ${SPHINX_INPUT} ${AKANTU_EXAMPLES_DOC_SRCS} ${_SPHINX_RST_SRCS} ${_SPHINX_MD_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/akantu.dox.j2"
COMMENT "Building HTML documentation with Sphinx in ${SPHINX_HTML_DIR}"
)
add_custom_target(sphinx-doc ALL
DEPENDS ${SPHINX_OUTPUT})
diff --git a/doc/dev-doc/akantu.dox.j2 b/doc/dev-doc/akantu.dox.j2
index 1af6a6939..b0451a98b 100644
--- a/doc/dev-doc/akantu.dox.j2
+++ b/doc/dev-doc/akantu.dox.j2
@@ -1,52 +1,55 @@
PROJECT_NAME = Akantu
#PROJECT_NUMBER = {{ akantu_version }}
STRIP_FROM_PATH = {{ akantu_source_path }}
STRIP_FROM_INC_PATH = {{ akantu_source_path }}
TAB_SIZE = 4
ALIASES = "rst=\verbatim embed:rst" \
"endrst=\endverbatim"
-QUIET = NO
+QUIET = YES
WARN_IF_UNDOCUMENTED = NO
WARN_IF_DOC_ERROR = NO
WARN_AS_ERROR = NO
INPUT = {{ akantu_source_path }}/src \
{{ akantu_source_path }}/test/ci/includes_for_ci
FILE_PATTERNS = *.c *.cc *.hh *.py
EXCLUDE = {{ akantu_source_path }}/src/common/aka_fwd.hh \
- {{ akantu_source_path }}/src/io/dumper/dumpable_dummy.hh
+ {{ akantu_source_path }}/src/io/dumper/dumpable_dummy.hh \
+ {{ akantu_source_path }}/src/synchronizer/communicator_dummy.hh \
{{ akantu_source_path }}/src/common/aka_config.hh.in
RECURSIVE = YES
EXAMPLE_PATH = {{ akantu_source_path }}/examples
EXAMPLE_RECURSIVE = YES
SOURCE_BROWSER = NO
GENERATE_HTML = NO
GENERATE_HTMLHELP = NO
USE_MATHJAX = YES
GENERATE_LATEX = NO
GENERATE_XML = YES
XML_OUTPUT = xml
-DOXYGEN_INCLUDE_PATH = {{ akantu_source_path }}/src/common \
+SEARCH_INCLUDES = YES
+INCLUDE_PATH = {{ akantu_source_path }}/src/common \
{{ akantu_source_path }}/src/fe_engine \
{{ akantu_source_path }}/src/mesh \
{{ akantu_source_path }}/src/model \
{{ akantu_source_path }}/test/ci/includes_for_ci
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
PREDEFINED = DOXYGEN \
__cplusplus=201402L \
"AKANTU_GET_MACRO(name, value, type) = type get##name() const;" \
"AKANTU_GET_MACRO_NOT_CONST(name, value, type) = type get##name();"
EXPAND_AS_DEFINED = __BEGIN_AKANTU__ \
__END_AKANTU__ \
__BEGIN_AKANTU_DUMPER__ \
__END_AKANTU_DUMPER__ \
AKANTU_SET_MACRO \
AKANTU_GET_MACRO_DEREF_PTR \
AKANTU_GET_MACRO_BY_ELEMENT_TYPE \
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST \
+ AKANTU_GET_MACRO_AUTO
COLLABORATION_GRAPH = NO
UML_LOOK = YES
TEMPLATE_RELATIONS = YES
CALL_GRAPH = YES
CALLER_GRAPH = YES
LOOKUP_CACHE_SIZE = 0
diff --git a/CHANGELOG.md b/doc/dev-doc/changelog.md
similarity index 84%
copy from CHANGELOG.md
copy to doc/dev-doc/changelog.md
index db355d6a0..c59ae3c92 100644
--- a/CHANGELOG.md
+++ b/doc/dev-doc/changelog.md
@@ -1,155 +1,196 @@
-## Version 5.0.2 (06-30-2023)
+# Version 5
+
+## Version 5.0.4
+
+### Added
+
+- SparseSolverEigen to have a simple solver in sequential
+- Python Wheel build for MacOS
+
+### Changed
+
+- DiffusionModel replaces HeatTransferModel
+- The class name HeatTransferModel is kept for backward compatibility
+- Bug fixes:
+ - Assemble of the K matrix for cohesive elements was wrong since v5
+ - Minor fixes
+
+
+## Version 5.0.3
+
+### Added
+
+- Extending contact mechanics python interface
+
+### Changed
+
+- Bug fixes in conctact mechanics
+
+
+## Version 5.0.2
### Added
- pypi package for python 3.11 and 3.12
-## Version 5.0.1 (05-05-2023)
+## Version 5.0.1
### Changed
- Bug fixes:
- bad constcorectness in arrays
- applyBC broken
- Extending python API
-## Version 5.0 (03-28-2023)
+## Version 5.0.0
### Changed
- C++ standard 17 is now accepted
- `Vector<T>` and `Matrix<T>` changed from internal types to Eigen::Matrix<T>
- `VectorProxy<T>` and `MatrixProxy<T>` are now `Eigen::Map<Eigen::Matrix<T>>`
This introduces a potential bug if codes like the following example where used:
```
for(auto && v_ : make_view(vectors, dim)) {
Vector<Real> v(v_);
...
}
```
With the new version the temporary vector `v` will be a deep copy of `v_`
instead of a shallow copy as in the previous version
### Added
- `make_view` as a static dimension version for vectors and matrices
`make_view<size>(vectors)` and `make_view<rows, cols>(matrices)`
- `zip` iterators can be named, in which case the
return tuple is a `named_tuple`.
```
for(auto && t : zip("a"_n = as, "b"_n = bs)) {
auto && a = t["a"_n];
auto && b = t["b"_n];
...
}
```
### Deprecated
- `begin_reinterpret` and `end_reinterpret` are error prone and deprecated in favor of `make_view`
- `storage()` members are deprecated in favor of `data()` in order to be compatible with the STL
- `get(.*)Energy(ElementType type, Idx index)` are deprecated in favor of `get(.*)Energy(const Element & element)`
elements can be implicitly created, `getEnergy({type, index, _not_ghost})`
- `begin_(node|element)_group` and `end_(node|element)_group` are replaced by `iterate(Node|Element)Groups`
- In the python interface:
- the global `setDebugLevel`, `getDebugLevel` and `printBacktrace` were moved in the sub-module `debug`
- the call to `finalize` is not needed
- `applyDirichketBC` was replaced by `applyBC`
### Deleted
- `getForce`, `firstType()`, `lastType()` that where deprecated in version 4.0
+# Version 4
-## Version 4.0 (09-21-2021)
+## Version 4.0.1
+
+### Changed
+
+- Bug fixes
+
+## Version 4.0.0
### 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 more 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)
+# Version 3
+
+## Version 3.2.0
### Added
- Activating PETSc solver back with the new solver interface
### Deprecated
- deprecating old C++ 03 code
-## 3.0 (2018-03)
+## Version 3.0.0
### 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 (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)
+# Version 2
+## Version 2.3.0
### Added
- swig python interface
-## 2.2 (2014-09)
+## Version 2.2.0
### Added
- Cohesive elements
-## 1.0 (2012-06)
+# Version 1
+
+## Version 1.0.0
### Added
- Continuum damage local and non-local
- Models: solid mechanics, structural mechanics, heat transfer
diff --git a/doc/dev-doc/changelog.rst b/doc/dev-doc/changelog.rst
deleted file mode 100644
index 540e1c93d..000000000
--- a/doc/dev-doc/changelog.rst
+++ /dev/null
@@ -1,63 +0,0 @@
-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 (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 7fb70a45c..06f2a0050 100644
--- a/doc/dev-doc/conf.py
+++ b/doc/dev-doc/conf.py
@@ -1,349 +1,339 @@
# -*- 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
__copyright__ = (
"Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)"
"Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)"
)
__license__ = "LGPLv3"
# -- 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 re
+import glob
import shutil
+import subprocess
+import sys
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.intersphinx",
+ "sphinx.ext.mathjax",
"sphinx.ext.viewcode",
+ "sphinx_rtd_theme",
"sphinxcontrib.bibtex",
"breathe",
+ "myst_parser",
+ # "sphinx_gallery.gen_gallery",
+ "sphinx_copybutton",
+ "sphinx_toolbox.collapse",
]
read_the_docs_build = os.environ.get("READTHEDOCS", None) == "True"
cmake_configure = os.environ.get("RUNNING_IN_CMAKE", None) == "True"
if read_the_docs_build:
akantu_path = "."
akantu_source_path = "../../"
elif cmake_configure:
akantu_path = "@CMAKE_CURRENT_BINARY_DIR@"
akantu_source_path = "@CMAKE_SOURCE_DIR@"
else: # most probably running by hand
akantu_path = "build-doc"
akantu_source_path = "../../"
try:
os.mkdir(akantu_path)
except FileExistsError:
pass
+
+if (
+ akantu_path == "@" + "CMAKE_CURRENT_BINARY_DIR" + "@"
+): # Concatenation is to avoid cmake to replace it
+ raise Exception("Something went really wrong")
+
+sys.path.insert(0, akantu_source_path)
+
# 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"
+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
+language = "en"
+
+
+def callback(dir, files):
+ keep_re = re.compile(r".*\.(svg|gif|png|md|rst|cc|dat|py)")
+ ignores = []
+ for file in files:
+ if (not keep_re.match(file) and
+ not os.path.isdir(os.path.join(dir, file))):
+ ignores.append(file)
+ return ignores
+
+
+shutil.copytree(
+ os.path.join(akantu_source_path, "examples"),
+ os.path.join(akantu_source_path, "doc", "dev-doc", "examples"),
+ ignore=callback,
+ dirs_exist_ok=True,
+)
# 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",
]
+exclude_patterns.extend(
+ glob.glob(
+ "examples/**/*.rst",
+ root_dir=os.path.join(akantu_source_path, "doc", "dev-doc"),
+ recursive=True,
+ )
+)
+
# 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)"
-)
+copyright = __copyright__
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"
+# 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
-mathjax_config = mathjax2_config
-
mathjax3_config = {
"tex": {
"macros": {
- "st": [r"\mathrm{#1}", 1],
- "mat": [r"\mathbf{#1}", 1],
- "half": [r"\frac{1}{2}", 0],
+ "st": ["\\mathrm{#1}", 1],
+ "mat": ["\\mathbf{#1}", 1],
+ "half": "\\frac{1}{2}",
},
- "packages": ["base", "ams"],
+ "packages": {"[+]": ["ams"]},
+ },
+ "loader": {
+ "load": ["[tex]/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"),
]
# -- 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)]
+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 = {}
+j2_template_path = "."
if read_the_docs_build or not cmake_configure:
j2_template_path = "."
elif cmake_configure:
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,
}
print(akantu_path)
j2_env = jinja2.Environment(
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_implementation_filename_extensions = [".c", ".cc", ".cpp", ".hh"]
breathe_show_enumvalue_initializer = True
-breathe_debug_trace_directives = True
-
-# -- Options for intersphinx extension ---------------------------------------
-
+breathe_debug_trace_directives = False
+breathe_short_warning = True
+
+# -- Gallery ------------------------------------------------------------------
+# sphinx_gallery_conf = {
+# 'examples_dirs': os.path.join(akantu_source_path, 'examples'),
+# 'gallery_dirs': os.path.join(akantu_source_path, 'doc',
+# 'dev-doc', 'auto_examples'),
+# 'download_all_examples': False,
+# 'plot_gallery': 'False',
+# 'only_warn_on_example_error': True,
+# 'log_level': {'backreference_missing': 'debug'},
+# }
+
+
+# -- 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/examples.rst b/doc/dev-doc/examples.rst
new file mode 100644
index 000000000..368975c9a
--- /dev/null
+++ b/doc/dev-doc/examples.rst
@@ -0,0 +1,2 @@
+.. include:: ./examples/README.rst
+
diff --git a/doc/dev-doc/index.rst b/doc/dev-doc/index.rst
index acd0ef46f..4c1e2a869 100644
--- a/doc/dev-doc/index.rst
+++ b/doc/dev-doc/index.rst
@@ -1,70 +1,72 @@
.. Akantu documentation master file, created by
sphinx-quickstart on Fri Apr 17 16:35:46 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Akantu: a FEM library
=====================
|license| |joss|
.. |joss| image:: https://joss.theoj.org/papers/3abf3c7945cc9a016a946ce9e02e357f/status.svg
:target: https://joss.theoj.org/papers/3abf3c7945cc9a016a946ce9e02e357f
.. |license| image:: https://img.shields.io/badge/license-LGPLv3-green
:target: https://www.gnu.org/licenses/lgpl-3.0.en.html
**Akantu** means a little element in *Kinyarwanda*, a Bantu language. From now
on it is also an opensource object-oriented *Finite-Element* library which has
the ambition to be generic and efficient. **Akantu** is developed within the
`LSMS <https://lsms.epfl.ch>`_ (Computational Solid Mechanics Laboratory)*, where
research is conducted at the interface of mechanics, material science, and
scientific computing. The open-source philosophy is important for any scientific
software project evolution. The collaboration permitted by shared codes enforces
sanity when users (and not only developers) can criticize the implementation
details. Akantu was born with the vision to associate genericity, robustness and
efficiency while benefiting the open-source visibility.
.. toctree::
:maxdepth: 2
:caption: User Manual
./manual/getting_started.rst
- ./manual/fe_engine.rst
- ./manual/solidmechanicsmodel.rst
- ./manual/heattransfermodel.rst
- ./manual/contactmechanicsmodel.rst
- ./manual/phasefieldmodel.rst
- ./manual/structuralmechanicsmodel.rst
+ ./manual/basic_types.rst
+ ./manual/models.rst
./manual/io.rst
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
+ :caption: Examples & Tutorials
+
+ ./examples.rst
+ ./tutorials.rst
+
+.. toctree::
+ :maxdepth: 1
:caption: Changelog
- ./changelog.rst
+ ./changelog.md
.. toctree::
:maxdepth: 2
:caption: API Reference
./reference.rst
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
:caption: Appendix
./manual/appendix.rst
.. toctree::
:maxdepth: 2
:caption: Bibliography
./manual/bibliography.rst
-Indices and tables
-==================
+.. toctree::
+ :maxdepth: 1
+ :caption: Indices and tables
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
+ ./manual/extra.rst
diff --git a/doc/dev-doc/manual/getting_started.rst b/doc/dev-doc/manual/basic_types.rst
similarity index 55%
copy from doc/dev-doc/manual/getting_started.rst
copy to doc/dev-doc/manual/basic_types.rst
index cd1b7e11c..1aa231448 100644
--- a/doc/dev-doc/manual/getting_started.rst
+++ b/doc/dev-doc/manual/basic_types.rst
@@ -1,577 +1,571 @@
-Getting Started
-===============
+Basic types
+===========
-Contributing
-------------
-
-Contributing new features, bug fixes
-````````````````````````````````````
-
-Any contribution is welcome, we are trying to follow a `gitflow <https://nvie.com/posts/a-successful-git-branching-model/>`_ workflow, so the project `developers` can create branches named `features/<name of my feature>` or `bugfixes/<name of the fix>` directly in the main `akantu` repository.
-External fellows can `Fork <https://gitlab.com/akantu/akantu/-/forks/new>`_ the project.
-In both cases the modifications have to be submitted in the form of a `Merge Request <https://gitlab.com/akantu/akantu/-/merge_requests/new>`_.
-
-Asking for help, reporting issues
-`````````````````````````````````
-
-If you want to ask for help concerning Akantu's compilation, usage or problem with the code do not hesitate to open an `Issue <https://gitlab.com/akantu/akantu/-/issues/new>`_ on gitlab. If you want to contribute and don't know where to start, you are also invited to open an issue.
-
-
-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 (pre-processor and Spirit)
- - zlib
- - Eigen3 (if not present the build system will try to download it)
-
-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)
-
-On ``.deb`` based Linux systems
-"""""""""""""""""""""""""""""""
-
-.. code-block:: bash
-
- > sudo apt install cmake libboost-dev zlib1g-dev gmsh libeigen3-dev
- # For parallel
- > sudo apt install mpi-default-dev libmumps-dev libscotch-dev
- # For sequential
- > sudo apt install libmumps-seq-dev
-
-Using ``conda``
-"""""""""""""""
-
-This works only for sequential computation since `mumps` from conda-forge is compiled without MPI support:
-
-.. code-block:: bash
-
- > conda create -n akantu
- > conda activate akantu
- > conda install boost cmake
- > conda install -c conda-forge mumps
-
-Using ``homebrew``
-""""""""""""""""""
-
-.. code-block:: bash
-
- > brew install gcc
- > brew install boost@1.76
- > brew tap brewsci/num
- > brew install brewsci-mumps --without-brewsci-parmetis
-
-If it does not work you can edit url to http://graal.ens-lyon.fr/MUMPS/MUMPS_5.3.5.tar.gz using the command:
-
-.. code-block:: bash
-
- > brew edit brewsci/num
-
-Configuring and compilation
-```````````````````````````
-
-`Akantu` is a `CMake <https://cmake.org/>`_ project, so to configure it, you can follow the usual way:
-
- .. code-block:: bash
-
- > cd akantu
- > mkdir build
- > cd build
- > ccmake ..
- [ Set the options that you need ]
- > make
- > make install
-
-On Mac OS X with ``homebrew``
-"""""""""""""""""""""""""""""
-You will need to specify the compiler explicitly::
-
-.. code-block:: bash
-
- > CC=gcc-12 CXX=g++-12 FC=gfortran-12 cmake ..
-
-Considering that ``homebrew` is installed in ``/opt/homebrew``
-Define the location of the ``Scotch`` library path:
-
-.. code-block:: bash
-
- > cmake .. -DSCOTCH_LIBRARY="/opt/homebrew/lib/libscotch.dylib;/opt/homebrew/lib/libscotcherr.dylib;/opt/homebrew/lib/libscotcherrexit.dylib"
-
-Specify path to all ``MUMPS`` libraries:
-
-.. code-block:: bash
-
- > cmake .. -DMUMPS_DIR=/opt/homebrew/opt/brewsci-mumps
-
-In case the above does not work, specify the ``MUMPS`` path manually using (e.g.):
-
-.. code-block:: bash
-
- > cmake .. -DMUMPS_LIBRARY_COMMON=/opt/homebrew/opt/brewsci-mumps/lib/libmumps_common.dylib
-
-If compilation does not work change the path of the failing libraries to brew downloads in `/opt/homebrew/`.
-
-Using the python interface
---------------------------
-
-You can install ``Akantu`` using pip, this will install a pre-compiled version, this works only on Linux machines for now::
-
- > 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 Renku.
-The tutorials are currently available: |renku|
-
-.. |renku| image:: https://user-content.gitlab-static.net/52a4794df1236b248c8fc870bd74e9d787c0e2cb/68747470733a2f2f72656e6b756c61622e696f2f72656e6b752d62616467652e737667
- :target: https://renkulab.io/projects/guillaume.anciaux/akantu-tutorials/sessions/new?autostart=1
-
-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. ::
-
- 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:`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:`Int
-<akantu::Int>` data named ``tag_1``.
-
-Using Arrays
-------------
+Array<T>
+--------
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;
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
+In this case the :math:`x` position of the eighth node 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
+ - :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.
+more into detail 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
+ - :cpp:func:`v.dot(x) <akantu::Vector::dot>` returns the dot product of
``v`` and ``x``
- - :cpp:func:`v.distance(x) <akantu::Vector::distance>` return the
+ - :cpp:func:`v.distance(x) <akantu::Vector::distance>` returns 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
+ - :cpp:func:`A.trace() <akantu::Matrix::trace>` returns the trace of ``A``
+ - :cpp:func:`A.det() <akantu::Matrix::det>` returns the determinant of ``A``
+ - :cpp:func:`A.doubleDot(B) <akantu::Matrix::doubleDot>` returns 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
+ eigenvalues and eigenvectors of ``A`` and stores 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`
+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 return 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 this::
+
+ // 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 this 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.
+
.. _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); }
});
+
+
+FEEngine
+--------
+
+The :cpp:class:`FEEngine<akantu::FEEngine>` interface is dedicated to handle the
+finite-element approximations and the numerical integration of the weak form. As
+we will see in Chapter :doc:`./solidmechanicsmodel`,
+:cpp:class:`Model<akantu::Model>` creates its own
+:cpp:class:`FEEngine<akantu::FEEngine>` object, hence the explicit creation of the
+object is not required.
+
+Mathematical Operations
+'''''''''''''''''''''''
+
+Using the :cpp:class:`FEEngine<akantu::FEEngine>` object, one can compute an interpolation,
+an integration or a gradient. A simple example is given below:
+
+.. code-block:: c++
+
+ // having a FEEngine object
+ auto fem = std::make_unique<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,
+ 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,
+ 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, ElementType type);
+
+
+Another example below shows how to integrate stress and strain fields over
+elements assigned to a particular material:
+
+.. code-block:: c++
+
+ UInt sp_dim{3}; // spatial dimension
+ UInt m{1}; // material index of interest
+ const auto type{_tetrahedron_4}; // element type
+
+ // get the stress and strain arrays associated to the material index m
+ const auto & strain_vec = model.getMaterial(m).getGradU(type);
+ const auto & stress_vec = model.getMaterial(m).getStress(type);
+
+ // get the element filter for the material index
+ const auto & 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);
+
+
+.. _sec-elements:
+
+Elements
+''''''''
+
+The base for every Finite-Elements computation is its mesh and the elements that
+are used within that mesh. The element types that can be used depend on the
+mesh, but also on the dimensionality of the problem (1D, 2D or 3D). In
+``Akantu``, several iso-parametric Lagrangian element types are supported (and
+one serendipity element). Each of these types is discussed in some detail below,
+starting with the 1D-elements all the way to the 3D-elements. More detailed
+information (shape function, location of Gaussian quadrature points, and so on)
+can be found in Appendix app:elements.
+
+Iso-parametric Elements
+```````````````````````
+
+1D
+""""
+
+There are two types of iso-parametric elements defined in 1D. These element
+types are called :cpp:enumerator:`_segment_2 <akantu::_segment_2>` and
+:cpp:enumerator:`_segment_3 <akantu::_segment_3>`, and are depicted
+schematically in :numref:`fig-elements-1D`. Some of the basic properties of
+these elements are listed in :numref:`tab-elements-1D`.
+
+.. _fig-elements-1D:
+.. figure:: figures/elements/segments.svg
+ :align: center
+
+ Schematic overview of the two 1D element types in ``Akantu``. In each
+ element, the node numbering as used in ``Akantu`` is indicated and the
+ quadrature points are highlighted (gray circles).
+
+
+.. _tab-elements-1D:
+.. csv-table:: Some basic properties of the two 1D iso-parametric elements in ``Akantu``
+ :header: "Element type", "Order", "#nodes", "#quad points"
+
+ ":cpp:enumerator:`_segment_2 <akantu::_segment_2>`", "linear", 2, 1
+ ":cpp:enumerator:`_segment_3 <akantu::_segment_3>`", "quadratic", 3, 2
+
+2D
+""""
+
+There are four types of iso-parametric elements defined in 2D. These element
+types are called :cpp:enumerator:`_triangle_3 <akantu::_triangle_3>`,
+:cpp:enumerator:`_triangle_6 <akantu::_triangle_6>`,
+:cpp:enumerator:`_quadrangle_4 <akantu::_quadrangle_4>` and
+:cpp:enumerator:`_quadrangle_8 <akantu::_quadrangle_8>`, and all of them are
+depicted in :numref:`fig-elements-2D`. As with the 1D elements, some of the most
+basic properties of these elements are listed in :numref:`tab-elements-2D`. It
+is important to note that the first element is linear, the next two quadratic
+and the last one cubic. Furthermore, the last element type (``_quadrangle_8``)
+is not a Lagrangian but a serendipity element.
+
+.. _fig-elements-2D:
+.. figure:: figures/elements/elements_2d.svg
+ :align: center
+
+ Schematic overview of the four 2D element types in ``Akantu``. In each
+ element, the node numbering as used in ``Akantu`` is indicated and the
+ quadrature points are highlighted (gray circles).
+
+
+.. _tab-elements-2D:
+.. csv-table:: Some basic properties of the 2D iso-parametric elements in ``Akantu``
+ :header: "Element type", "Order", "#nodes", "#quad points"
+
+ ":cpp:enumerator:`_triangle_3 <akantu::_triangle_3>`", "linear", 3, 1
+ ":cpp:enumerator:`_triangle_6 <akantu::_triangle_6>`", "quadratic", 6, 3
+ ":cpp:enumerator:`_quadrangle_4 <akantu::_quadrangle_4>`", "linear", 4, 4
+ ":cpp:enumerator:`_quadrangle_8 <akantu::_quadrangle_8>`", "quadratic", 8, 9
+
+3D
+""""
+
+In ``Akantu``, there are three types of iso-parametric elements defined in 3D.
+These element types are called :cpp:enumerator:`_tetrahedron_4
+<akantu::_tetrahedron_4>`, :cpp:enumerator:`_tetrahedron_10
+<akantu::_tetrahedron_10>` and :cpp:enumerator:`_hexadedron_8
+<akantu::_hexadedron_8>`, and all of them are depicted schematically in
+:numref:`fig-elements-3D`. As with the 1D and 2D elements some of the most basic
+properties of these elements are listed in :numref:`tab-elements-3D`.
+
+.. _fig-elements-3D:
+.. figure:: figures/elements/elements_3d.svg
+ :align: center
+
+ Schematic overview of the three 3D element types in ``Akantu``. In each
+ element, the node numbering as used in ``Akantu`` is indicated and the
+ quadrature points are highlighted (gray circles).
+
+.. _tab-elements-3D:
+.. csv-table:: Some basic properties of the 3D iso-parametric elements in ``Akantu``
+ :header: "Element type", "Order", "#nodes", "#quad points"
+
+ ":cpp:enumerator:`_tetrahedron_4 <akantu::_tetrahedron_4>`", "linear", 4, 1
+ ":cpp:enumerator:`_tetrahedron_10 <akantu::_tetrahedron_10>`", "quadratic", 10, 4
+ ":cpp:enumerator:`_hexadedron_8 <akantu::_hexadedron_8>`", "cubic", 8, 8
+
+Cohesive Elements
+`````````````````
+
+The cohesive elements that have been implemented in ``Akantu`` are based
+on the work of Ortiz and Pandolfi :cite:`ortiz1999`. Their main
+properties are reported in :numref:`tab-coh-cohesive_elements`.
+
+.. _fig-smm-coh-cohesive2d:
+.. figure:: figures/elements/cohesive_2d_6.svg
+ :align: center
+
+ Cohesive element in 2D for quadratic triangular elements T6.
+
+.. _tab-coh-cohesive_elements:
+.. csv-table:: Some basic properties of the cohesive elements in ``Akantu``.
+ :header: "Element type", "Facet type", "Order", "#nodes", "#quad points"
+
+ ":cpp:enumerator:`_cohesive_1d_2 <_cohesive_1d_2>`", ":cpp:enumerator:`_point_1 <akantu::_point_1>`", "linear", 2, 1
+ ":cpp:enumerator:`_cohesive_2d_4 <akantu::_cohesive_2d_4>`", ":cpp:enumerator:`_segment_2 <akantu::_segment_2>`", "linear", 4, 1
+ ":cpp:enumerator:`_cohesive_2d_6 <akantu::_cohesive_2d_6>`", ":cpp:enumerator:`_segment_3 <akantu::_segment_3>`", "quadratic", 6, 2
+ ":cpp:enumerator:`_cohesive_3d_6 <akantu::_cohesive_3d_6>`", ":cpp:enumerator:`_triangle_3 <akantu::_triangle_3>`","linear", 6, 1
+ ":cpp:enumerator:`_cohesive_3d_12 <akantu::_cohesive_3d_12>`", ":cpp:enumerator:`_triangle_6 <akantu::_triangle_6>`", "quadratic", 12, 3
+
+
+Structural Elements
+```````````````````
+
+Bernoulli Beam Elements
+"""""""""""""""""""""""
+
+These elements allow to compute the displacements and rotations of structures
+constituted by Bernoulli beams. ``Akantu`` defines them for both 2D and 3D
+problems respectively in the element types :cpp:enumerator:`_bernoulli_beam_2
+<akantu::_bernoulli_beam_2>` and :cpp:enumerator:`_bernoulli_beam_3
+<akantu::_bernoulli_beam_3>`. A schematic depiction of a beam element is shown
+in :numref:`fig-elements-bernoulli` and some of its properties are listed in
+:numref:`tab-elements-bernoulli`.
+
+.. note::
+ Beam elements are of mixed order: the axial displacement is
+ linearly interpolated while transverse displacements and rotations
+ use cubic shape functions.
+
+.. _fig-elements-bernoulli:
+.. figure:: figures/elements/bernoulli_2.svg
+ :align: center
+
+ Schematic depiction of a Bernoulli beam element (applied to 2D and
+ 3D) in ``Akantu``. The node numbering as used in ``Akantu`` is
+ indicated, and the quadrature points are highlighted (gray
+ circles).
+
+.. _tab-elements-bernoulli:
+.. csv-table:: Some basic properties of the beam elements in ``Akantu``
+ :header: "Element type", "Dimension", "# nodes", "# quad. points", "# d.o.f."
+
+ ":cpp:enumerator:`_bernoulli_beam_2 <akantu::_bernoulli_beam_2>`", "2D", 2, 3, 6
+ ":cpp:enumerator:`_bernoulli_beam_3 <akantu::_bernoulli_beam_3>`", "3D", 2, 3, 12
diff --git a/doc/dev-doc/manual/conf.py b/doc/dev-doc/manual/conf.py
deleted file mode 100644
index a1a462801..000000000
--- a/doc/dev-doc/manual/conf.py
+++ /dev/null
@@ -1,209 +0,0 @@
-# -*- 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
-__copyright__ = (
- "Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)"
- "Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)"
-)
-__license__ = "LGPLv3"
-
-
-# -- 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 sys
-# sys.path.insert(0, os.path.abspath('.'))
-
-
-# -- Project information -----------------------------------------------------
-
-project = 'Akantu'
-copyright = '2019-20, Laboratoire de Simulation en Mécanique des Solides, EPFL'
-author = 'Nicolas Richart'
-
-# The short X.Y version
-version = ''
-# The full version, including alpha/beta/rc tags
-release = '3.0.0'
-
-
-# -- 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.mathjax',
- 'sphinx.ext.viewcode',
- # 'breathe'
-]
-
-# 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 = []
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = None
-
-# Default programming language
-highlight_language = 'cpp'
-
-
-# -- Options for HTML output -------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages. See the documentation for
-# a list of builtin themes.
-#
-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']
-
-# 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 = {}
-
-
-# -- 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': '',
-
- # 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'),
-]
-
-
-# -- 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
-
-# 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 -------------------------------------------------
-
-# If on RTD build, run doxygen
-# on_read_the_docs = os.environ.get('READTHEDOCS') == 'True'
-
-# if on_read_the_docs:
-# subprocess.call('cd ../../; mkdir -p build/doxygen; '
-# + 'doxygen doxygen/Doxyfile', shell=True)
-
-# breathe_projects = {
-# 'akantu': '../../../build/doc/doxygen/xml'
-# }
-
-# breathe_default_project = 'akantu'
-
-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/constitutive-laws.rst b/doc/dev-doc/manual/constitutive-laws.rst
index 6b76d5957..1a28ed49d 100644
--- a/doc/dev-doc/manual/constitutive-laws.rst
+++ b/doc/dev-doc/manual/constitutive-laws.rst
@@ -1,1407 +1,1407 @@
.. _sect-smm-cl:
Constitutive Laws
------------------
+`````````````````
In order to compute an element’s response to deformation, one needs to
use an appropriate constitutive relationship. The constitutive law is
used to compute the element’s stresses from the element’s strains.
In the finite-element discretization, the constitutive formulation is
applied to every quadrature point of each element. When the implicit
formulation is used, the tangent matrix has to be computed.
| The chosen materials for the simulation have to be specified in the
mesh file or, as an alternative, they can be assigned using the at
``element_material`` vector. For
every material assigned to the problem one has to specify the material
characteristics (constitutive behavior and material properties) using
the text input file (see :ref:`sect-io-material`).
| In order to conveniently store values at each quadrature in a material point
``Akantu`` provides a special data structure, the at :cpp:class:`InternalField
<akantu::InternalField>`. The internal fields are inheriting from the at
:cpp:class:`ElementTypeMapArray <akantu::ElementTypeMapArray>`. Furthermore,
it provides several functions for initialization, auto-resizing and auto
removal of quadrature points.
The constitutive law is precised within an input file. The dedicated material section
is then read by :cpp:func:`initFull <akantu::SolidMechanicsModel::initFull>`
method of :cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>` which
initializes the different materials specified with the following convention
.. code-block:: python
material constitutive_law [
name = value
rho = value
...
]
where *constitutive_law* is the adopted constitutive law, followed by
the material properties listed one by line in the bracket (*e.g.*,
``name`` and density :math:``rho``. Some constitutive laws can also
have an *optional flavor*.
For certain materials, it is possible to activate the large deformation
strain and stress evaluations. Internally the strain measure becomes
the right Cauchy–Green deformation tensor and the evaluated stress
measure becomes the Piola-Kirchhoff stress tensor. This is activated by using:
.. code-block:: python
material constitutive_law [
finite_deformation = true # Activates the large deformation routines (bool)
...
]
Sometimes it is also desired to generate random distributions of
internal parameters. An example might be the critical stress at which
the material fails. To generate such a field, in the text input file, a
random quantity needs be added to the base value:
All parameters are real numbers. For the uniform distribution, minimum
and maximum values have to be specified. Random parameters are defined
as a :math:`base` value to which we add a random number that follows the
chosen distribution.
The
`Uniform <http://en.wikipedia.org/wiki/Uniform_distribution_(continuous)>`__
distribution is gives a random values between in :math:`[min, max)`. The
`Weibull <http://en.wikipedia.org/wiki/Weibull_distribution>`__
distribution is characterized by the following cumulative distribution
function:
.. math:: F(x) = 1- e^{-\left({x/\lambda}\right)^m}
which depends on :math:`m` and :math:`\lambda`, which are the shape
parameter and the scale parameter. These random distributions are
different each time the code is executed. In order to obtain always the
same one, it possible to manually set the *seed* that is the number from
which these pseudo-random distributions are created. This can be done by
adding the following line to the input file *outside* the material
parameters environments:
.. code-block::
seed = 1.0
where the value 1.0 can be substituted with any number. Currently
``Akantu`` can reproduce always the same distribution when the seed is
specified *only* in serial. The value of the *seed* can be also
specified directly in the code (for instance in the main file) with the
command:
.. code-block::
RandGenerator<Real>::seed(1.0)
The same command, with empty brackets, can be used to check the value of
the *seed* used in the simulation.
The following sections describe the constitutive models implemented in
``Akantu``.
-----
Elastic
-```````
+'''''''
The elastic law is a commonly used constitutive relationship that can be
used for a wide range of engineering materials (*e.g.*, metals,
concrete, rock, wood, glass, rubber, etc.) provided that the strains
remain small (*i.e.*, small deformation and stress lower than yield
strength).
The elastic laws are often expressed as
:math:`\boldsymbol{\sigma} =
\boldsymbol{C}:\boldsymbol{\varepsilon}` with
where :math:`\boldsymbol{\sigma}` is the Cauchy stress
tensor, :math:`\boldsymbol{\varepsilon}` represents the
infinitesimal strain tensor and :math:`\boldsymbol{C}` is
the elastic modulus tensor.
.. _sect-smm-linear-elastic-isotropic:
Linear isotropic
-''''''''''''''''
+""""""""""""""""
Keyword: **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material elastic [
name = steel
rho = 7800 # density (Real)
E = 2.1e11 # young's modulus (Real)
nu = 0.3 # poisson's ratio (Real)
Plane_stress = false # Plane stress simplification (only 2D problems) (bool)
finite_deformation = false # activates the evaluation of strains with green's tensor (bool)
]
Available energies Energies:
- ``potential``: elastic potential energy
-----
The linear isotropic elastic behavior is described by Hooke’s law, which
states that the stress is linearly proportional to the applied strain
(material behaves like an ideal spring), as illustrated in
 :numref:`fig:smm:cl:el`.
.. figure:: figures/cl/stress_strain_el.svg
:alt: Elastic strain-stress curve
:name: fig:smm:cl:el
:width: 60.0%
Stress-strain curve of elastic material and schematic representation of
Hooke's law, denoted as a spring.
The equation that relates the strains to the displacements is: point)
from the displacements as follows:
.. math::
\label{eqn:smm:strain_inf}
\boldsymbol{\varepsilon} =
\frac{1}{2} \left[ \nabla_0 \boldsymbol{u}+\nabla_0 \boldsymbol{u}^T \right]
where :math:`\boldsymbol{\varepsilon}` represents the
infinitesimal strain tensor,
:math:`\nabla_{0}\boldsymbol{u}` the displacement gradient
tensor according to the initial configuration. The constitutive equation
for isotropic homogeneous media can be expressed as:
.. math::
\label{eqn:smm:material:constitutive_elastic}
\boldsymbol{\sigma } =\lambda\mathrm{tr}(\boldsymbol{\varepsilon})\boldsymbol{I}+2 \mu\boldsymbol{\varepsilon}
where :math:`\boldsymbol{\sigma}` is the Cauchy stress
tensor (:math:`\lambda` and :math:`\mu` are the the first and second
Lame’s coefficients).
In Voigt notation this correspond to
.. math::
\begin{aligned}
\left[\begin{array}{c}
\sigma_{11}\\
\sigma_{22}\\
\sigma_{33}\\
\sigma_{23}\\
\sigma_{13}\\
\sigma_{12}\\
\end{array}\right]
&= \frac{E}{(1+\nu)(1-2\nu)}\left[
\begin{array}{cccccc}
1-\nu & \nu & \nu & 0 & 0 & 0\\
\nu & 1-\nu & \nu & 0 & 0 & 0\\
\nu & \nu & 1-\nu & 0 & 0 & 0\\
0 & 0 & 0 & \frac{1-2\nu}{2} & 0 & 0 \\
0 & 0 & 0 & 0 & \frac{1-2\nu}{2} & 0 \\
0 & 0 & 0 & 0 & 0 & \frac{1-2\nu}{2} \\
\end{array}\right]
\left[\begin{array}{c}
\varepsilon_{11}\\
\varepsilon_{22}\\
\varepsilon_{33}\\
2\varepsilon_{23}\\
2\varepsilon_{13}\\
2\varepsilon_{12}\\
\end{array}\right]\end{aligned}
This formulation is not sufficient to represent all elastic material
behavior. Some materials have characteristic orientation that have to be
taken into account. To represent this anisotropy a more general
stress-strain law has to be used, as shown below.
-----
.. _sect-smm-linear-elastic-anisotropic:
Linear anisotropic
-''''''''''''''''''
+""""""""""""""""""
Keyword: **elastic_anisotropic**
Material description with input file:
.. code-block:: python
#input.dat
material elastic_anisotropic [
name = aluminum
rho = 1.6465129043044597 # density (Real)
C11 = 105.092023 # Coefficient ij of material tensor C (Real)
C12 = 59.4637759 # all the 36 values
C13 = 59.4637759 # in Voigt notation can be entered
C14 = 0 # zero coefficients can be omited
C15 = 0
C16 = 0
C22 = 105.092023
C23 = 59.4637759
C24 = 0
C25 = 0
C26 = 0
C33 = 105.092023
C34 = 0
C35 = 0
C36 = 0
C44 = 30.6596356
C45 = 0
C46 = 0
C55 = 30.6596356
C56 = 0
C66 = 30.6596356
n1 = [-1, 1, 0] # Direction of first material axis (Vector<Real>)
n2 = [ 1, 1, 1] # Direction of second material axis (Vector<Real>)
n3 = [ 1, 1, -2] # Direction of thrid material axis (Vector<Real>)
]
----
We define the elastic modulus tensor as follows:
.. math::
\begin{aligned}
\left[\begin{array}{c}
\sigma_{11}\\
\sigma_{22}\\
\sigma_{33}\\
\sigma_{23}\\
\sigma_{13}\\
\sigma_{12}\\
\end{array}\right]
&= \left[
\begin{array}{cccccc}
c_{11} & c_{12} & c_{13} & c_{14} & c_{15} & c_{16}\\
c_{21} & c_{22} & c_{23} & c_{24} & c_{25} & c_{26}\\
c_{31} & c_{32} & c_{33} & c_{34} & c_{35} & c_{36}\\
c_{41} & c_{42} & c_{43} & c_{44} & c_{45} & c_{46}\\
c_{51} & c_{52} & c_{53} & c_{54} & c_{55} & c_{56}\\
c_{61} & c_{62} & c_{63} & c_{64} & c_{65} & c_{66}\\
\end{array}\right]
\left[\begin{array}{c}
\varepsilon_{11}\\
\varepsilon_{22}\\
\varepsilon_{33}\\
2\varepsilon_{23}\\
2\varepsilon_{13}\\
2\varepsilon_{12}\\
\end{array}\right]\end{aligned}
To simplify the writing of input files the :math:`\boldsymbol{C}` tensor
is expressed in the material basis. And this basis as to be given too.
This basis :math:`\Omega_{{\mathrm{mat}}}
= \{\boldsymbol{n_1}, \boldsymbol{n_2}, \boldsymbol{n_3}\}`
is used to define the rotation :math:`R_{ij} =
\boldsymbol{n_j} . \boldsymbol{e_i}`. And
:math:`\boldsymbol{C}` can be rotated in the global basis
:math:`\Omega
= \{\boldsymbol{e_1}, \boldsymbol{e_2}, \boldsymbol{e_3}\}`
as follow:
.. math::
\begin{aligned}
\boldsymbol{C}_{\Omega} &= \boldsymbol{R}_1 \boldsymbol{C}_{\Omega_{{\mathrm{mat}}}} \boldsymbol{R}_2\\
\boldsymbol{R}_1 &= \left[
\begin{array}{cccccc}
R_{11} R_{11} & R_{12} R_{12} & R_{13} R_{13} & R_{12} R_{13} & R_{11} R_{13} & R_{11} R_{12}\\
R_{21} R_{21} & R_{22} R_{22} & R_{23} R_{23} & R_{22} R_{23} & R_{21} R_{23} & R_{21} R_{22}\\
R_{31} R_{31} & R_{32} R_{32} & R_{33} R_{33} & R_{32} R_{33} & R_{31} R_{33} & R_{31} R_{32}\\
R_{21} R_{31} & R_{22} R_{32} & R_{23} R_{33} & R_{22} R_{33} & R_{21} R_{33} & R_{21} R_{32}\\
R_{11} R_{31} & R_{12} R_{32} & R_{13} R_{33} & R_{12} R_{33} & R_{11} R_{33} & R_{11} R_{32}\\
R_{11} R_{21} & R_{12} R_{22} & R_{13} R_{23} & R_{12} R_{23} & R_{11} R_{23} & R_{11} R_{22}\\
\end{array}\right]\\
\boldsymbol{R}_2 &= \left[
\begin{array}{cccccc}
R_{11} R_{11} & R_{21} R_{21} & R_{31} R_{31} & R_{21} R_{31} & R_{11} R_{31} & R_{11} R_{21}\\
R_{12} R_{12} & R_{22} R_{22} & R_{32} R_{32} & R_{22} R_{32} & R_{12} R_{32} & R_{12} R_{22}\\
R_{13} R_{13} & R_{23} R_{23} & R_{33} R_{33} & R_{23} R_{33} & R_{13} R_{33} & R_{13} R_{23}\\
R_{12} R_{13} & R_{22} R_{23} & R_{32} R_{33} & R_{22} R_{33} & R_{12} R_{33} & R_{12} R_{23}\\
R_{11} R_{13} & R_{21} R_{23} & R_{31} R_{33} & R_{21} R_{33} & R_{11} R_{33} & R_{11} R_{23}\\
R_{11} R_{12} & R_{21} R_{22} & R_{31} R_{32} & R_{21} R_{32} & R_{11} R_{32} & R_{11} R_{22}\\
\end{array}\right]\\\end{aligned}
-----
.. _sect-smm-linear-elastic-orthotropic:
Linear orthotropic
-''''''''''''''''''
+""""""""""""""""""
Keyword: **elastic_orthotropic**
Inherits from **elastic_anisotropic**
Material description with input file:
.. code-block:: python
#input.dat
material elastic_orthotropic [
name = test_mat_1
rho = 1 # density
n1 = [-1, 1, 0] # Direction of first material axis (Vector<Real>)
n2 = [ 1, 1, 1] # Direction of second material axis (Vector<Real>)
n3 = [ 1, 1, -2] # Direction of thrid material axis (Vector<Real>)
E1 = 1 # Young's modulus in direction n1 (Real)
E2 = 2 # Young's modulus in direction n2 (Real)
E3 = 3 # Young's modulus in direction n3 (Real)
nu12 = 0.1 # Poisson's ratio 12 (Real)
nu13 = 0.2 # Poisson's ratio 13 (Real)
nu23 = 0.3 # Poisson's ratio 23 (Real)
G12 = 0.5 # Shear modulus 12 (Real)
G13 = 1 # Shear modulus 13 (Real)
G23 = 2 # Shear modulus 23 (Real)
]
-----
A particular case of anisotropy is when the material basis is orthogonal
in which case the elastic modulus tensor can be simplified and rewritten
in terms of 9 independents material parameters.
.. math::
\begin{aligned}
\left[\begin{array}{c}
\sigma_{11}\\
\sigma_{22}\\
\sigma_{33}\\
\sigma_{23}\\
\sigma_{13}\\
\sigma_{12}\\
\end{array}\right]
&= \left[
\begin{array}{cccccc}
c_{11} & c_{12} & c_{13} & 0 & 0 & 0 \\
& c_{22} & c_{23} & 0 & 0 & 0 \\
& & c_{33} & 0 & 0 & 0 \\
& & & c_{44} & 0 & 0 \\
& \text{sym.} & & & c_{55} & 0 \\
& & & & & c_{66}\\
\end{array}\right]
\left[\begin{array}{c}
\varepsilon_{11}\\
\varepsilon_{22}\\
\varepsilon_{33}\\
2\varepsilon_{23}\\
2\varepsilon_{13}\\
2\varepsilon_{12}\\
\end{array}\right]\end{aligned}
.. math::
\begin{aligned}
c_{11} &= E_1 (1 - \nu_{23}\nu_{32})\Gamma \qquad c_{22} = E_2 (1 - \nu_{13}\nu_{31})\Gamma \qquad c_{33} = E_3 (1 - \nu_{12}\nu_{21})\Gamma\\
c_{12} &= E_1 (\nu_{21} - \nu_{31}\nu_{23})\Gamma = E_2 (\nu_{12} - \nu_{32}\nu_{13})\Gamma\\
c_{13} &= E_1 (\nu_{31} - \nu_{21}\nu_{32})\Gamma = E_2 (\nu_{13} - \nu_{21}\nu_{23})\Gamma\\
c_{23} &= E_2 (\nu_{32} - \nu_{12}\nu_{31})\Gamma = E_3 (\nu_{23} - \nu_{21}\nu_{13})\Gamma\\
c_{44} &= \mu_{23} \qquad c_{55} = \mu_{13} \qquad c_{66} = \mu_{12} \\
\Gamma &= \frac{1}{1 - \nu_{12} \nu_{21} - \nu_{13} \nu_{31} - \nu_{32} \nu_{23} - 2 \nu_{21} \nu_{32} \nu_{13}}\end{aligned}
The Poisson ratios follow the rule
:math:`\nu_{ij} = \nu_{ji} E_i / E_j`.
-----
.. _sect-smm-cl-neohookean:
Neo-Hookean
-'''''''''''
+"""""""""""
Keyword: **neohookean**
Inherits from **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material neohookean [
name = material_name
rho = 7800 # density (Real)
E = 2.1e11 # young's modulus (Real)
nu = 0.3 # poisson's ratio (Real)
]
-----
The hyperelastic Neo-Hookean constitutive law results from an extension
of the linear elastic relationship (Hooke’s Law) for large deformation.
Thus, the model predicts nonlinear stress-strain behavior for bodies
undergoing large deformations.
.. figure:: figures/cl/stress_strain_neo.svg
:alt: Neo-hookean Stress-strain curve.
:name: fig:smm:cl:neo_hookean
:width: 40.0%
Neo-hookean Stress-strain curve.
As illustrated in :numref:`fig:smm:cl:neo_hookean`, the behavior
is initially linear and the mechanical behavior is very close to the
corresponding linear elastic material. This constitutive relationship,
which accounts for compressibility, is a modified version of the one
proposed by Ronald Rivlin :cite:`Belytschko:2000`.
The strain energy stored in the material is given by:
.. math::
\label{eqn:smm:constitutive:neohookean_potential}
\Psi(\boldsymbol{C}) = \frac{1}{2}\lambda_0\left(\ln J\right)^2-\mu_0\ln J+\frac{1}{2}
\mu_0\left(\mathrm{tr}(\boldsymbol{C})-3\right)
where :math:`\lambda_0` and :math:`\mu_0` are, respectively, Lamé’s
first parameter and the shear modulus at the initial configuration.
:math:`J` is the jacobian of the deformation gradient
(:math:`\boldsymbol{F}=\nabla_{\!\!\boldsymbol{X}}\boldsymbol{x}`):
:math:`J=\text{det}(\boldsymbol{F})`. Finally
:math:`\boldsymbol{C}` is the right Cauchy-Green
deformation tensor.
Since this kind of material is used for large deformation problems, a
finite deformation framework should be used. Therefore, the Cauchy
stress (:math:`\boldsymbol{\sigma}`) should be computed
through the second Piola-Kirchhoff stress tensor
:math:`\boldsymbol{S}`:
.. math:: \boldsymbol{\sigma } = \frac{1}{J}\boldsymbol{F}\boldsymbol{S}\boldsymbol{F}^T
Finally the second Piola-Kirchhoff stress tensor is given by:
.. math::
\boldsymbol{S} = 2\frac{\partial\Psi}{\partial\boldsymbol{C}} = \lambda_0\ln J
\boldsymbol{C}^{-1}+\mu_0\left(\boldsymbol{I}-\boldsymbol{C}^{-1}\right)
The parameters to indicate in the material file are the same as those
for the elastic case: ``E`` (Young’s modulus), ``nu`` (Poisson’s ratio).
-----
.. _sect-smm-cl-ve:
Visco-Elastic
-`````````````
+'''''''''''''
.. _sect-smm-cl-sls:
Standard-Linear Solid
-'''''''''''''''''''''
+"""""""""""""""""""""
Keyword: **sls_deviatoric**
Inherits from **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material sls_deviatoric [
name = material_name
rho = 1000 # density (Real)
E = 2.1e9 # young's modulus (Real)
nu = 0.4 # poisson's ratio (Real)
Eta = 1. # Viscosity (Real)
Ev = 0.5 # Stiffness of viscous element (Real)
Plane_stress = false # Plane stress simplification (bool, only 2D problems)
]
Since this material inherits from :cpp:class:`MaterialElastic
<akantu::MaterialElastic>` the parameter :math:`E` preceeds :math:`E_{\mathrm{inf}}`. So only :math:`E`
and :math:`E_v` can be set, :math:`E_{\mathrm{inf}}` is deduced by :math:`E_{\mathrm{inf}} = E - E_{v}`.
-----
Visco-elasticity is characterized by strain rate dependent behavior.
Moreover, when such a material undergoes a deformation it dissipates
energy. This dissipation results in a hysteresis loop in the
stress-strain curve at every loading cycle (see
:numref:`fig:smm:cl:visco-elastic:hyst`).
In principle, it can be applied to many materials, since all materials
exhibit a visco-elastic behavior if subjected to particular conditions
(such as high temperatures).
.. figure:: figures/cl/stress_strain_visco.svg
:name: fig:smm:cl:visco-elastic:hyst
:align: center
:width: 40.0%
Characteristic stress-strain behavior of a visco-elastic material with hysteresis loop
.. figure:: figures/cl/visco_elastic_law.svg
:name: fig:smm:cl:visco-elastic:model
:align: center
:width: 40.0%
Schematic representation of the standard rheological linear solid visco-elastic model
The standard rheological linear solid model (see Sections 10.2 and 10.3
of :cite:`simo92`) has been implemented in ``Akantu``. This
model results from the combination of a spring mounted in parallel with
a spring and a dashpot connected in series, as illustrated in
:numref:`fig:smm:cl:visco-elastic:model`.
The advantage of this model is that it allows to account for creep or
stress relaxation. The equation that relates the stress to the strain is
(in 1D):
.. math::
\frac{d\varepsilon(t)}{dt} = \left ( E_{\mathrm{inf}} + E_{v} \right ) ^ {-1} \cdot \left [ \frac{d\sigma(t)}{dt} + \frac{E_{v}}{\eta}\sigma(t) - \frac{E_{\mathrm{inf}}E_V}{\eta}\varepsilon(t) \right ]
where :math:`\eta` is the viscosity. The equilibrium condition is unique and is
attained in the limit, as :math:`t \to \infty`. At this stage, the response is
elastic and depends on the Young’s modulus :math:`E`. The mandatory parameters
for the material file are the following: ``rho`` (density), ``E`` (Young’s
modulus), ``nu`` (Poisson’s ratio), ``Plane_Stress`` (if set to zero plane
strain, otherwise plane stress), ``eta`` (dashpot viscosity) and ``Ev``
(stiffness of the viscous element).
Note that the current standard linear solid model is applied only on the
deviatoric part of the strain tensor. The spheric part of the strain
tensor affects the stress tensor like an linear elastic material.
-----
.. _sect-smm-cl-maxwell:
Maxwell Chain Visco-Elasticity
-''''''''''''''''''''''''''''''
+""""""""""""""""""""""""""""""
Keyword: **viscoelastic_maxwell**
Inherits from **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material viscoelastic_maxwell [
name = material_name
rho = 1000 # density (Real)
Einf = 5.e9 # Infinite time Young's modulus (Real)
nu = 0.4 # poisson's ratio (Real)
Ev = [1.e9, 2.e9, 3.e9] # Maxwell elements' stiffness values (Vector<Real>)
Eta = [1.e14, 2.e16, 3.e16] # Dashpot elements' viscosity values (Vector<Real>)
Plane_stress = false # Plane stress simplification (bool, only 2D problems)
]
----
.. figure:: figures/cl/maxwell_chain.png
:name: fig-smm-cl-visco-elastic-maxwell
:align: center
:width: 40.0%
Schematic representation of the Maxwell chain
A different visco-elastic rheological model available to users is the
generalized Maxwell chain (see :cite:`de_borst_finiteelement_1994` and Section 46.7.4 of :cite:`diana_manual`).
It consists of a series of sequential spring-dashpots
(Maxwell elements) placed in parallel with one single spring (see
:numref:`fig-smm-cl-visco-elastic-maxwell`). The relation between stresses and
strain comes from
.. math:: \sigma \left ( t \right ) = \int_{-\infty}^{t} E \left ( t, \tau \right ) \mathbf{D} \dot{\varepsilon} d\tau
where :math:`E(t,\tau)` is the time-dependent relaxation function, :math:`\tau`
is the loading age, and :math:`\mathbf{D}` is the dimensionless matrix relating
a 3D deformation state to a 1D relaxation function. The relaxation function is
expanded in the exponential series
.. math::
:label: eqn-relaxation-function
E \left ( t, \tau \right ) = E_{0} + \sum_{\alpha=1}^{n} E_{\alpha} e^{- \frac{t- \tau}{\lambda_{\alpha}}}
where the relaxation time of each Maxwell element is defined as
:math:`\lambda_{\alpha}=\eta_{\alpha} / E_{\alpha}` with :math:`\eta_{\alpha}`
being the viscosity of a dash-pot. Assuming a constant strain rate within each
time step, the analytical integration of the right-hand side of
:eq:`eqn-relaxation-function` leads to the following form
.. math::
\sigma \left ( t + \Delta t \right ) = E_{0} \mathbf{D} \varepsilon +
\sum_{\alpha=1}^n \left ( \left ( 1 - e^{\frac{- \Delta t}{\lambda_{\alpha}}} \right )
\frac{E_{\alpha} \lambda_{\alpha}}{\Delta t} \mathbf{D} \delta \varepsilon +
e^{\frac{-\Delta t}{\lambda_{\alpha}}} \sigma_{\alpha} \left ( t \right ) \right )
with :math:`\sigma_{\alpha}(t)` being the internal stress within each Maxwell
element, defined as
.. math:: \sigma_{\alpha} \left ( t \right ) = \mathbf{D} \int_0^t E_{\alpha} e^{\frac{-t- \tau}{\lambda_{\alpha}}} \dot{\varepsilon} d \tau
The first term under the sum sign in above equation could be seen as the
effective stiffness of a single Maxwell element multiplied by the matrix
:math:`\mathbf{D}` and the strain increment :math:`\Delta \varepsilon`:
.. math::
E_{\alpha}^{ef} = \left ( 1- e^{\frac{-Δt}{λ_α}} \right ) \frac{E_α λ_α}{Δt}
Time increment :math:`Δt` controls the rate dependency of the effective
stiffness. By limit analysis, we find the limiting values of the effective
stiffness which are equal to :math:`E_0` for infinitely slow loading (:math:`Δt`
tending to infinity) and :math:`E_0+ΣE_α` for infinitely fast (:math:`Δt` tending to
0). At the end of each converged time step, the internal stress
:math:`σ_α(t)` is updated according to
.. math::
σ_α \left ( t \right ) = σ_α \left ( t - Δt \right ) e^{\frac{-Δt}{λ_α}} + E_α^{ef} \mathbf{D} Δε
The mandatory parameters for the material file are the following: ``rho``
(density), ``nu`` (Poisson’s ratio), ``Plane_Stress`` (if set to zero plane
strain, otherwise plane stress), ``Einf`` (infinite time Young’s modulus),
``Ev`` (Maxwell elements' stiffness values stored in a vector), ``Eta``
(dashpots' viscosity values stored in a vector).
The Maxwell model is applied on the entire strain tensor and does not
distinguish between its deviatoric and hydrostatic components. Note that the
time step has to be specified for the model using current material both for
static and dynamic simulations:
.. code-block:: c++
model.setTimeStep(time_step_value);
.. _sect-smm-cl-plastic:
Plastic
-```````
+'''''''
Small-Deformation Plasticity
-''''''''''''''''''''''''''''
+""""""""""""""""""""""""""""
Keyword: **plastic_linear_isotropic_hardening**
Inherits from **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material plastic_linear_isotropic_hardening [
name = material_name
rho = 1000 # density (Real)
E = 2.1e9 # young's modulus (Real)
nu = 0.4 # poisson's ratio (Real)
h = 0.1 # Hardening modulus (Real)
sigma_y = 1e6 # Yield stress (Real)
]
Energies:
- ``potential``: elastic part of the potential energy
- ``plastic``: dissipated plastic energy (integrated over time)
-----
The small-deformation plasticity is a simple plasticity material
formulation which accounts for the additive decomposition of strain into
elastic and plastic strain components. This formulation is applicable to
infinitesimal deformation where the additive decomposition of the strain
is a valid approximation. In this formulation, plastic strain is a
shearing process where hydrostatic stress has no contribution to
plasticity and consequently plasticity does not lead to volume change.
:numref:`fig:smm:cl:Lin-strain-hard` shows the linear strain
hardening elasto-plastic behavior according to the additive
decomposition of strain into the elastic and plastic parts in
infinitesimal deformation as
.. math::
\boldsymbol{\varepsilon} &= \boldsymbol{\varepsilon}^e +\boldsymbol{\varepsilon}^p\\
\boldsymbol{\sigma} &= 2G(\boldsymbol{\varepsilon}^e) + \lambda \mathrm{tr}(\boldsymbol{\varepsilon}^e)\boldsymbol{I}
.. figure:: figures/cl/isotropic_hardening_plasticity.svg
:name: fig:smm:cl:Lin-strain-hard
:align: center
Stress-strain curve for the small-deformation plasticity with linear isotropic hardening.
In this class, the von Mises yield criterion is used. In the von Mises
yield criterion, the yield is independent of the hydrostatic stress.
Other yielding criteria such as Tresca and Gurson can be easily
implemented in this class as well.
In the von Mises yield criterion, the hydrostatic stresses have no
effect on the plasticity and consequently the yielding occurs when a
critical elastic shear energy is achieved.
.. math::
\label{eqn:smm:constitutive:von Mises}
f = \sigma_{{\mathrm{eff}}} - \sigma_y = \left(\frac{3}{2} {\boldsymbol{\sigma}}^{{\mathrm{tr}}} : {\boldsymbol{\sigma}}^{{\mathrm{tr}}}\right)^\frac{1}{2}-\sigma_y (\boldsymbol{\varepsilon}^p)
.. math::
\label{eqn:smm:constitutive:yielding}
f < 0 \quad \textrm{Elastic deformation,} \qquad f = 0 \quad \textrm{Plastic deformation}
where :math:`\sigma_y` is the yield strength of the material which can
be function of plastic strain in case of hardening type of materials and
:math:`{\boldsymbol{\sigma}}^{{\mathrm{tr}}}` is the
deviatoric part of stress given by
.. math::
\label{eqn:smm:constitutive:deviatoric stress}
{\boldsymbol{\sigma}}^{{\mathrm{tr}}}=\boldsymbol{\sigma} - \frac{1}{3} \mathrm{tr}(\boldsymbol{\sigma}) \boldsymbol{I}
After yielding :math:`(f = 0)`, the normality hypothesis of plasticity
determines the direction of plastic flow which is normal to the tangent
to the yielding surface at the load point. Then, the tensorial form of
the plastic constitutive equation using the von Mises yielding criterion
(see equation 4.34) may be written as
.. math::
\label{eqn:smm:constitutive:plastic contitutive equation}
\Delta {\boldsymbol{\varepsilon}}^p = \Delta p \frac {\partial{f}}{\partial{\boldsymbol{\sigma}}}=\frac{3}{2} \Delta p \frac{{\boldsymbol{\sigma}}^{{\mathrm{tr}}}}{\sigma_{{\mathrm{eff}}}}
In these expressions, the direction of the plastic strain increment (or
equivalently, plastic strain rate) is given by
:math:`\frac{{\boldsymbol{\sigma}}^{{\mathrm{tr}}}}{\sigma_{{\mathrm{eff}}}}`
while the magnitude is defined by the plastic multiplier
:math:`\Delta p`. This can be obtained using the *consistency condition*
which impose the requirement for the load point to remain on the
yielding surface in the plastic regime.
Here, we summarize the implementation procedures for the
small-deformation plasticity with linear isotropic hardening:
#. Compute the trial stress:
.. math:: {\boldsymbol{\sigma}}^{{\mathrm{tr}}} = {\boldsymbol{\sigma}}_t + 2G\Delta \boldsymbol{\varepsilon} + \lambda \mathrm{tr}(\Delta \boldsymbol{\varepsilon})\boldsymbol{I}
#. Check the Yielding criteria:
.. math:: f = (\frac{3}{2} {\boldsymbol{\sigma}}^{{\mathrm{tr}}} : {\boldsymbol{\sigma}}^{{\mathrm{tr}}})^{1/2}-\sigma_y (\boldsymbol{\varepsilon}^p)
#. Compute the Plastic multiplier:
.. math::
\begin{aligned}
d \Delta p &= \frac{\sigma^{tr}_{eff} - 3G \Delta P^{(k)}- \sigma_y^{(k)}}{3G + h}\\
\Delta p^{(k+1)} &= \Delta p^{(k)}+ d\Delta p\\
\sigma_y^{(k+1)} &= (\sigma_y)_t+ h\Delta p
\end{aligned}
#. Compute the plastic strain increment:
.. math:: \Delta {\boldsymbol{\varepsilon}}^p = \frac{3}{2} \Delta p \frac{{\boldsymbol{\sigma}}^{{\mathrm{tr}}}}{\sigma_{{\mathrm{eff}}}}
#. Compute the stress increment:
.. math:: {\Delta \boldsymbol{\sigma}} = 2G(\Delta \boldsymbol{\varepsilon}-\Delta \boldsymbol{\varepsilon}^p) + \lambda \mathrm{tr}(\Delta \boldsymbol{\varepsilon}-\Delta \boldsymbol{\varepsilon}^p)\boldsymbol{I}
#. Update the variables:
.. math::
\begin{aligned}
{\boldsymbol{\varepsilon^p}} &= {\boldsymbol{\varepsilon}}^p_t+{\Delta {\boldsymbol{\varepsilon}}^p}\\
{\boldsymbol{\sigma}} &= {\boldsymbol{\sigma}}_t+{\Delta \boldsymbol{\sigma}}
\end{aligned}
We use an implicit integration technique called *the radial return method* to
obtain the plastic multiplier. This method has the advantage of being
unconditionally stable, however, the accuracy remains dependent on the step
size. The plastic parameters to indicate in the material file are:
:math:`\sigma_y` (Yield stress) and ``h`` (Hardening modulus). In addition, the
elastic parameters need to be defined as previously mentioned: ``E`` (Young’s
modulus), ``nu`` (Poisson’s ratio).
-----
Damage
-``````
+""""""
In the simplified case of a linear elastic and brittle material,
isotropic damage can be represented by a scalar variable :math:`d`,
which varies from :math:`0` to :math:`1` for no damage to fully broken
material respectively. The stress-strain relationship then becomes:
.. math:: \boldsymbol{\sigma} = (1-d)\, \boldsymbol{C}:\boldsymbol{\varepsilon}
where :math:`\boldsymbol{\sigma}`,
:math:`\boldsymbol{\varepsilon}` are the Cauchy stress and
strain tensors, and :math:`\boldsymbol{C}` is the elastic
stiffness tensor. This formulation relies on the definition of an
evolution law for the damage variable. In ``Akantu``, many possibilities
exist and they are listed below.
----
.. _sect-smm-cl-damage-marigo:
Marigo
-''''''
+""""""
Keyword: **marigo**
Inherits from **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material marigo [
name = material_name
rho = 1000 # density (Real)
E = 2.1e9 # young's modulus (Real)
nu = 0.4 # poisson's ratio (Real)
Plane_stress = false # Plane stress simplification (bool, only 2D problems)
Yd = 0.1 # Hardening modulus (Random)
Sd = 1. # Damage energy (Real)
]
Energies:
- ``dissipated``: energy dissipated in damage
-----
This damage evolution law is energy based as defined by Marigo
:cite:`marigo81a`, :cite:`lemaitre96a`. It is an isotropic damage law.
.. math::
\begin{aligned}
Y &= \frac{1}{2}\boldsymbol{\varepsilon}:\boldsymbol{C}:\boldsymbol{\varepsilon}\\
F &= Y - Y_d - S d\\
d &= \left\{
\begin{array}{l l}
\mathrm{min}\left(\frac{Y-Y_d}{S},\;1\right) & \mathrm{if}\; F > 0\\
\mathrm{unchanged} & \mathrm{otherwise}
\end{array}
\right.\end{aligned}
In this formulation, :math:`Y` is the strain energy release rate,
:math:`Y_d` the rupture criterion and :math:`S` the damage energy. The
non-local version of this damage evolution law is constructed by
averaging the energy :math:`Y`.
.. _sect-smm-cl-damage-mazars:
Mazars
''''''
Keyword: **mazars**
Inherits from **elastic**
Material description with input file:
.. code-block:: python
#input.dat
material mazars [
name = concrete
rho = 3000 # density (Real)
E = 32e9 # young's modulus (Real)
nu = 0.2 # poisson's ratio (Real)
K0 = 9.375e-5 # Damage threshold (Real)
At = 1.15 # Parameter damage traction 1 (Real)
Bt = 10000 # Parameter damage traction 2 (Real)
Ac = 0.8 # Parameter damage compression 1 (Real)
Bc = 1391.3 # Parameter damage compression 2 (Real)
beta = 1.00 # Parameter for shear (Real)
]
Energies:
- ``dissipated``: energy dissipated in damage
-----
This law introduced by Mazars :cite:`mazars84a` is a
behavioral model to represent damage evolution in concrete. This model
does not rely on the computation of the tangent stiffness, the damage is
directly evaluated from the strain.
The governing variable in this damage law is the equivalent strain
:math:`\varepsilon_{{\mathrm{eq}}} =
\sqrt{<\boldsymbol{\varepsilon}>_+:<\boldsymbol{\varepsilon}>_+}`,
with :math:`<.>_+` the positive part of the tensor. This part is defined
in the principal coordinates (I, II, III) as
:math:`\varepsilon_{{\mathrm{eq}}} =
\sqrt{<\boldsymbol{\varepsilon_I}>_+^2 + <\boldsymbol{\varepsilon_{II}}>_+^2 + <\boldsymbol{\varepsilon_{III}}>_+^2}`.
The damage is defined as:
.. math::
\begin{aligned}
D &= \alpha_t^\beta D_t + (1-\alpha_t)^\beta D_c\\
D_t &= 1 - \frac{\kappa_0 (1- A_t)}{\varepsilon_{{\mathrm{eq}}}} - A_t \exp^{-B_t(\varepsilon_{{\mathrm{eq}}}-\kappa_0)}\\
D_c &= 1 - \frac{\kappa_0 (1- A_c)}{\varepsilon_{{\mathrm{eq}}}} - A_c
\exp^{-B_c(\varepsilon_{{\mathrm{eq}}}-\kappa_0)}\\
\alpha_t &= \frac{\sum_{i=1}^3<\varepsilon_i>_+\varepsilon_{{\mathrm{nd}}\;i}}{\varepsilon_{{\mathrm{eq}}}^2}\end{aligned}
With :math:`\kappa_0` the damage threshold, :math:`A_t` and :math:`B_t`
the damage parameter in traction, :math:`A_c` and :math:`B_c` the damage
parameter in compression, :math:`\beta` is the shear parameter.
:math:`\alpha_t` is the coupling parameter between traction and
compression, the :math:`\varepsilon_i` are the eigenstrain and the
:math:`\varepsilon_{{\mathrm{nd}}\;i}` are the eigenvalues of the strain
if the material were undamaged.
The coefficients :math:`A` and :math:`B` are the post-peak asymptotic
value and the decay shape parameters.
.. _sect:smm:CLNL:
Non-Local Constitutive Laws
-```````````````````````````
+'''''''''''''''''''''''''''
Continuum damage modeling of quasi-brittle materials undergo significant
softening after the onset of damage. This fast growth of damage causes a loss of
ellipticity of partial differential equations of equilibrium. Therefore, the
numerical simulation results won't be objective anymore, because the dissipated
energy will depend on mesh size used in the simulation. One way to avoid this
effect is the use of non-local damage formulations. In this approach a local
quantity such as the strain is replaced by its non-local average, where the size
of the domain, over which the quantitiy is averaged, depends on the underlying
material microstructure. ``Akantu`` provides non-local versions of many
constitutive laws for damage. Examples are for instance the material
:ref:`sect-smm-cl-damage-mazars` and the material
:ref:`sect-smm-cl-damage-marigo`, that can be used in a non-local context. In
order to use the corresponding non-local formulation the user has to define the
non-local material he wishes to use in the text input file:
.. code-block:: none
material constitutive_law_non_local [
name = material_name
rho = $value$
...
]
where ``constitutive_law_non_local`` is the name of the non-local constitutive law, *e.g.* `marigo_non_local`.
In addition to the material the non-local neighborhood, that should be used for the averaging process needs to be defined in the material file as well:
.. code-block:: none
non_local neighborhood_name weight_function_type [
radius = $value$
...
weight_function weight_parameter [
damage_limit = $value$
...
]
]
for the non-local averaging, *e.g.* ``base_wf``, followed by the properties of the non-local neighborhood, such as the radius, and the weight function parameters. It is important to notice that the non-local neighborhood must have the same name as the material to which the neighborhood belongs!
The following two sections list the non-local constitutive laws and different type of weight functions available in ``Akantu``.
\subsection{Non-local constitutive laws}
Let us consider a body having a volume :math:`V` and a boundary :math:`\Gamma`. The stress-strain relation for a non-local damage model can be described as follows:
.. _eq:non-local-const:
.. math:: \vec{\sigma} = (1-\bar{d}) \vec{D}:\epsilon
with :math:`\vec{D}` the elastic moduli tensor, :math:`\sigma` the stress tensor, :math:`\epsilon` the strain tensor and :math:`\bar{d}` the non-local damage variable. Note that this stres-strain relationship is similar to the relationship defined in Damage model except :math:`\bar{d}`. The non-local damage model can be extended to the damage constitutive laws: :ref:`sect-smm-cl-damage-marigo` and :ref:`sect-smm-cl-damage-mazars`.
The non-local damage variable :math:`\bar{d}` is defined as follows:
.. _eq:non-local-damage:
.. math:: \bar{d}(\vec{x}) = \int_{V}W(\vec{x}, \vec{y}) d(\vec{y}) dV(\vec{y})
with :math:`W(\vec{x},\vec{y})` the weight function which averages local damage variables to describe the non-local interactions. A list of available weight functions and its functionalities in \akantu are explained in the next section.
Non-local weight functions
-''''''''''''''''''''''''''
+""""""""""""""""""""""""""
The available weight functions in ``Akantu`` are follows:
- ``base_weight_function``: This weight function averages local damage variables by using a bell-shape function on spatial dimensions.
- ``damaged_weight_function``: A linear-shape weight function is applied to average local damage variables. Its slope is determined by damage variables. For example, the damage variables for an element which is highly damaged are averaged over large spatial dimension (linear function including a small slope).
- ``remove_damaged_weight_function``: This weight function averages damage values by using a bell-shape function as ``base_weight_function``, but excludes elements which are fully damaged.
- ``remove_damaged_with_damage_rate_weight_function``: A bell-shape function is applied to average local damage variables for elements having small damage rates.
- ``stress_based_weight_function``: Non local integral takes stress states, and use the states to construct weight function: an ellipsoid shape. Detailed explanations of this weight function are given in Giry et al. :cite:`giry13a`.
-----
.. _sec-cohesive-laws:
Cohesive Constitutive laws
-``````````````````````````
+''''''''''''''''''''''''''
.. _ssect-smm-cl-coh-snozzi:
Linear Irreversible Law
-'''''''''''''''''''''''
+"""""""""""""""""""""""
Keyword: **cohesive_linear**
Material description with input file:
.. code-block:: python
#input.dat
material cohesive_linear [
name = cohesive
sigma_c = 0.1 # critical stress sigma_c (default: 0)
G_c = 1e-2 # Mode I fracture energy
beta = 0. # weighting parameter for sliding and normal opening (default: 0)
penalty = 0. # stiffness in compression to prevent penetration (α in the text)
kappa = 1. # ration between mode-I and mode-II fracture energy (Gc_II/Gc_I)
contact_after_breaking = true # Activation of contact when the elements are fully damaged
max_quad_stress_insertion = false # Insertion of cohesive element when stress is high
# enough just on one quadrature point
# if false the average stress on facet's quadrature points is used
]
-----
.. figure:: figures/cl/linear_cohesive_law.svg
:alt: Irreversible cohesive laws for explicit simulations.
:name: fig:smm:coh:linear_cohesive_law
:align: center
:width: 60.0%
Irreversible cohesive laws for explicit simulations.
`Akantu` includes the Snozzi-Molinari :cite:`snozzi_cohesive_2013`
linear irreversible cohesive law (see
:numref:`fig:smm:coh:linear_cohesive_law`). It is an extension to
the Camacho-Ortiz :cite:`camacho_computational_1996` cohesive law in
order to make dissipated fracture energy path-dependent. The concept
of free potential energy is dropped and a new independent parameter
:math:`\kappa` is introduced:
.. math::
\kappa = \frac{G_\mathrm{c, II}}{G_\mathrm{c, I}}
where :math:`G_\mathrm{c, I}` and :math:`G_\mathrm{c, II}` are the
necessary works of separation per unit area to open completely a
cohesive zone under mode I and mode II, respectively. Their model yields to the
following equation for cohesive tractions :math:`\vec{T}` in case of crack
opening :math:`{\delta}`:
.. math::
\vec{T} = \left( \frac{\beta^2}{\kappa} \Delta_\mathrm{t} \vec{t} +
\Delta_\mathrm{n} \vec{n} \right)
\frac{\sigma_\mathrm{c}}{\delta}
\left( 1- \frac{\delta}{\delta_\mathrm{c}} \right)
= \hat{\vec T}\,
\frac{\sigma_\mathrm{c}}{\delta}
\left( 1- \frac{\delta}{\delta_\mathrm{c}} \right)
:label: eq-smm-coh-tractions
where :math:`\sigma_\mathrm{c}` is the material strength along the fracture,
:math:`\delta_\mathrm{c}` the critical effective displacement after which
cohesive tractions are zero (complete decohesion), :math:`\Delta_\mathrm{t}`
and :math:`\Delta_\mathrm{n}` are the tangential and normal components of
the opening displacement vector :math:`\vec{\Delta}`, respectively. The
parameter :math:`\beta` is a weight that indicates how big the tangential
opening contribution is. The effective opening displacement is:
.. math::
\delta = \sqrt{\frac{\beta^2}{\kappa^2} \Delta_\mathrm{t}^2 + \Delta_\mathrm{n}^2}
In case of unloading or reloading :math:`\delta < \delta_\mathrm{max}`,
tractions are calculated as:
.. math::
\begin{eqnarray}
T_\mathrm{n} &= \Delta_\mathrm{n}\, \frac{\sigma_\mathrm{c}}{\delta_\mathrm{max}} \left( 1- \frac{\delta_\mathrm{max}}{\delta_\mathrm{c}} \right) \\
T_\mathrm{t} &= \frac{\beta^2}{\kappa}\, \Delta_\mathrm{t}\, \frac{\sigma_\mathrm{c}}{\delta_\mathrm{max}} \left( 1- \frac{\delta_\mathrm{max}}{\delta_\mathrm{c}} \right)
\end{eqnarray}
so that they vary linearly between the origin and the maximum attained
tractions. As shown in :numref:`fig:smm:coh:linear_cohesive_law`,
in this law, the dissipated and reversible energies are:
.. math::
\begin{eqnarray}
E_\mathrm{diss} &= \frac{1}{2} \sigma_\mathrm{c}\, \delta_\mathrm{max}\\[1ex]
E_\mathrm{rev} &= \frac{1}{2} T\, \delta
\end{eqnarray}
Moreover, a damage parameter :math:`D` can be defined as:
.. math::
D = \min \left(
\frac{\delta_\mathrm{max}}{\delta_\mathrm{c}},1 \right)
which varies from 0 (undamaged condition) and 1 (fully
damaged condition). This variable can only increase because damage is
an irreversible process. A simple penalty contact model has been incorporated
in the cohesive law so that normal tractions can be returned in
case of compression:
.. math::
T_\mathrm{n} = \alpha \Delta_\mathrm{n} \quad\text{if}\quad
\Delta_\mathrm{n}\quad <\quad 0
where :math:`\alpha` is a stiffness parameter that defaults to zero. The
relative contact energy is equivalent to reversible energy but in
compression.
The material name of the linear decreasing cohesive law is
``material_cohesive_linear`` and its parameters with their respective default
values are:
- ``sigma_c = 0``
- ``delta_c = 0``
- ``beta = 0``
- ``G_c = 0``
- ``kappa = 1``
- ``penalty = 0``
where ``G_c`` corresponds to :math:`G_\mathrm{c, I}`. A random number
generator can be used to assign a random :math:`\sigma_\mathrm{c}` to each
facet following a given distribution (see
Section :ref:`sect-smm-cl`). Only one parameter between ``delta_c``
and ``G_c`` has to be specified. For random :math:`\sigma_\mathrm{c}`
distributions, the chosen parameter of these two is kept fixed and the
other one is varied.
The bi-linear constitutive law works exactly the same way as the linear
one, except for the additional parameter ``delta_0`` that by
default is zero. Two examples for the extrinsic and intrinsic cohesive
elements and also an example to assign different properties to
inter-granular and trans-granular cohesive elements can be found in
the folder ``examples/cohesive_element/``.
----
.. _ssect:smm:cl:coh-friction:
Linear Cohesive Law with Friction
-'''''''''''''''''''''''''''''''''
+"""""""""""""""""""""""""""""""""
Keyword: **cohesive_linear_friction**
Material description with input file:
.. code-block:: python
#input.dat
material cohesive_linear_friction [
name = interface
beta = 1 # weighting parameter for sliding and normal opening (default: 0)
G_c = 30e-3 # Mode I fracture energy
penalty = 1.0e6 # stiffness in compression to prevent penetration (α in the text)
sigma_c = 2.0 # critical stress sigma_c (default: 0)
contact_after_breaking = true # Activation of contact when the elements are fully damaged
mu = 0.5 # Maximum value of the friction coefficient
penalty_for_friction = 5.0e3 # Penalty parameter for the friction behavior
]
-----
This law represents a variation of the linear irreversible cohesive of
the previous section, which adds friction. The friction behavior is
approximated with an elasto-plastic law, which relates the friction
force to the relative sliding between the two faces of the cohesive
element. The slope of the elastic branch is called
``penalty_for_friction``, and is defined by the user, together
with the friction coefficient, as a material property. The friction
contribution evolves with the damage of the cohesive law: it is null
when the damage is zero, and it becomes maximum when the damage is
equal to one. This is done by defining a current value of the
friction coefficient (mu) that increases linearly with the damage, up
to the value of the friction coefficient defined by the user. The
yielding plateau of the friction law is given by the product of the
current friction coefficient and the local compression stress acting
in the cohesive element. Such an approach is equivalent to a
node-to-node contact friction. Its accuracy is acceptable only for
small displacements.
The material name of the linear cohesive law with friction is
``material_cohesive_linear_friction``. Its additional parameters
with respect to those of the linear cohesive law without friction,
with the respective default values, are:
- ``mu = 0``
- ``penalty_for_friction = 0``
.. _ssect:smm:cl:coh-fatigue:
Linear Cohesive Law with Fatigue
-''''''''''''''''''''''''''''''''
+""""""""""""""""""""""""""""""""
Keyword: **cohesive_linear_fatigue**
Material description with input file:
.. code-block:: python
#input.dat
material cohesive_linear_fatigue [
name = cohesive
sigma_c = 1 # critical stress sigma_c (default: 0)
beta = 1 # weighting parameter for sliding and normal opening (default: 0)
delta_c = 1 # Critical displacement
delta_f = 1 # delta_f (normalization of opening rate to alter reloading stiffness after fatigue)
count_switches = true # Count the opening/closing switches per element
]
-----
This law represents a variation of the linear irreversible cohesive
law of the previous section, that removes the hypothesis of elastic
unloading-reloading cycles. With this law, some energy is dissipated
also during unloading and reloading with hysteresis. The
implementation follows the work of :cite:`nguyen2001`. During the
unloading-reloading cycle, the traction increment is computed as
.. math::
\dot{T} =
\begin{cases}
K^- \, \dot{\delta} & \text{if $\dot{\delta} < 0$} \\
K^+ \, \dot{\delta} & \text{if $\dot{\delta} > 0$} \\
\end{cases}
where :math:`\dot{\delta}` and :math:`\dot{T}` are respectively the effective
opening displacement and the cohesive traction increments with respect
to time, while :math:`K^-` and :math:`K^+` are respectively the unloading and
reloading incremental stiffness. The unloading path is linear and
results in an unloading stiffness
.. math::
K^- = \frac{T_\mathrm{max}}{\delta_\mathrm{max}}
where :math:`T_\mathrm{max}` and :math:`\delta_\mathrm{max}` are the maximum
cohesive traction and the effective opening displacement reached
during the precedent loading phase. The unloading stiffness remains
constant during the unloading phase. On the other hand the reloading
stiffness increment :math:`\dot{K}^+` is calculated as
.. math::
\dot{K}^+ =
\begin{cases}
- K^+ \, \dot{\delta} / \delta_\mathrm{f} & \text{if $\dot{\delta}
> 0$} \\
\left( K^+ - K^- \right) \, \dot{\delta} / \delta_\mathrm{f} &
\text{if $\dot{\delta}$ < $0$}
\end{cases}
where :math:`\delta_\mathrm{f}` is a material parameter (refer
to :cite:`vocialta15` for more details). During unloading the stiffness
:math:`K^+` tends to :math:`K^-`, while during reloading :math:`K^+` gets decreased at
every time step. If the cohesive traction during reloading exceeds the
upper limit given by equation :eq:`eq-smm-coh-tractions`, it is
recomputed following the behavior of the linear decreasing cohesive
law for crack opening.
.. _ssect:smm:cl:coh-exponential:
Exponential Cohesive Law
-'''''''''''''''''''''''''
+""""""""""""""""""""""""
Keyword: **cohesive_exponential**
Material description with input file:
.. code-block:: python
#input.dat
material cohesive_exponential [
name = coh1
sigma_c = 1.5e6 # critical stress sigma_c (default: 0)
beta = 1 # weighting parameter for sliding and normal opening (default: 0)
delta_c = 1e-4 # Critical displacement
exponential_penalty = true # Is contact penalty following the exponential law?
contact_tangent = 1.0 # Ratio of contact tangent over the initial exponential tangent
]
-----
Ortiz and Pandolfi proposed this cohesive law in 1999 :cite:`ortiz1999`. The
traction-opening equation for this law is as follows:
.. math::
T = e \sigma_c \frac{\delta}{\delta_c}e^{-\delta/ \delta_c}
:label: eq:exponential_law
This equation is plotted in :numref:`fig:smm:cl:ecl`. The term
:math:`\partial{\vec{T}}/ \partial{\delta}` after the necessary derivation
can expressed as
.. math::
\frac{\partial{\vec{T}}} {\partial{\delta}} = \hat{\vec{T}} \otimes
\frac {\partial{(T/\delta)}}{\partial{\delta}}
\frac{\hat{\vec{T}}}{\delta}+ \frac{T}{\delta} \left[ \beta^2 \mat{I} +
\left(1-\beta^2\right) \left(\vec{n} \otimes \vec{n}\right)\right]
:label: eq:tangent_cohesive
where
.. math::
\frac{\partial{(T/ \delta)}}{\partial{\delta}} = \left\{\begin{array} {l l}
-e \frac{\sigma_c}{\delta_c^2 }e^{-\delta / \delta_c} & \quad \text{if}
\delta \geq \delta_{max}\\
0 & \quad \text{if} \delta < \delta_{max}, \delta_n > 0
\end{array} \right.
As regards the behavior in compression, two options are available:
a contact penalty approach with stiffness following the formulation of
the exponential law and a contact penalty approach with constant
stiffness. In the second case, the stiffness is defined as a function
of the tangent of the exponential law at the origin.
.. figure:: figures/cl/cohesive_exponential.png
:alt: Exponential cohesive law
:name: fig:smm:cl:ecl
:align: center
Exponential cohesive law
diff --git a/doc/dev-doc/manual/contactmechanicsmodel.rst b/doc/dev-doc/manual/contactmechanicsmodel.rst
index 617895736..839854cf1 100644
--- a/doc/dev-doc/manual/contactmechanicsmodel.rst
+++ b/doc/dev-doc/manual/contactmechanicsmodel.rst
@@ -1,472 +1,476 @@
Contact Mechanics Model
-=======================
+-----------------------
The contact mechanics model is a specific implementation of
:cpp:class:`Model <akantu::Model>` interface to handle contact between
bodies.
Theory
-------
+``````
.. _fig-contactmechanicsmodel-schematic:
.. figure:: figures/contact_mechanics_schematic.png
:align: center
:width: 90%
Basic notation for the contact between two bodies.
Let us consider two deformable bodies, represented as :math:`\Omega_\alpha`,
:math:`\alpha=1, 2`. The boundary :math:`\Gamma_\alpha` of a body is divided
into three non-intersecting regions : :math:`\Gamma^D_\alpha` with
prescribed displacements, :math:`\Gamma^N_\alpha` with prescribed tractions
and :math:`\Gamma^C_\alpha` where the two bodies :math:`\Omega_1` can potentially
come into contact such that:
.. math::
\Gamma^D_\alpha \cup \Gamma^N_\alpha \cup \Gamma^C_\alpha =
\Gamma_\alpha, \quad \Gamma^D_\alpha \cap \Gamma^N_\alpha \cap
\Gamma^C_\alpha = \emptyset
The motion of the two bodies is described in a fixed spatial frame
defined by orthonormal basis :math:`[\boldsymbol{e}_x,
\boldsymbol{e}_y, \boldsymbol{e}_z]` by mapping
:math:`\mathcal{M}_\alpha^t` in time interval :math:`t \in [0, T]`. In
*reference* configuration :math:`i.e.~ t=0`, the position vector for
an arbitrary point on body :math:`\Omega_\alpha` is represented as
:math:`\boldsymbol{X}_\alpha` and in actual configuration the points
are denoted by small letters for example :math:`\boldsymbol{x}`.
:numref:`fig-contactmechanicsmodel-schematic` shows the motion of two
bodies from the *reference* to actual configuration. During the
motion, the bodies can potentially come in contact along
:math:`\Gamma^C_\alpha` as shown in
:numref:`fig-contactmechanicsmodel-schematic`, termed as *potential
contact zone*. Upon contact, two physical conditions need to be
satisfied :math:`(i)` the two surfaces :math:`\Gamma^C_\alpha` cannot
interpenetrate at any time during motion :math:`(ii)` forces must be
exerted by bodies along the :math:`\Gamma^C_\alpha` to resist the
interpenetration as well as relative motion along the contacting
surfaces. Of the two conditions, the non-penetration of bodies can be
defined by a *gap function* :math:`g` which represents the separation
between the two bodies:
.. math::
g = (\boldsymbol{r} -\boldsymbol{\rho}).\boldsymbol{n}
where :math:`\boldsymbol{r} \in \mathcal{M}[\Gamma^C_1]` is the
position of point :math:`\boldsymbol{X}_1` at time :math:`t` ,
:math:`\boldsymbol{\rho} \in \mathcal{M}[\Gamma^C_2]` is the closest
point projection of :math:`\boldsymbol{r}` and :math:`\boldsymbol{n}`
is the outward normal at :math:`\boldsymbol{\rho}` (see
:numref:`fig-contactmechanicsmodel-schematic` b). To preclude the
interpenetration, the *gap function* is constrained with :math:`g \geq 0`, as it is shown in
\Cref{fig:body-contact}b. When the two bodies eventually come in
contact, the gap vanishes :math:`i.e.~ g=0` which leads to the
development of tractions :math:`\boldsymbol{T}_\alpha` along the
contact interface. Thus, the boundary value problem can be formulated
for the two bodies :math:`\Omega_\alpha` with contact constraints as an
extra boundary condition:
.. math::
\boldsymbol{T}\Big |_{{\Gamma^C}_{\alpha}} = \boldsymbol{T}_\alpha
Solution spaces :math:`\mathcal{U}_\alpha` and weighting spaces
:math:`\mathcal{W}_\alpha` are defined for each body:
.. math::
\mathcal{U}_\alpha = \{ \boldsymbol{u}_\alpha: \Omega_\alpha \to \mathbb{R}^d ~|~ \boldsymbol{u}=\boldsymbol{u}[\boldsymbol{x}_\alpha]~ \forall~\boldsymbol{x}_\alpha \in \Gamma^D_\alpha \}
.. math::
\mathcal{W}_\alpha = \{ \boldsymbol{w}_\alpha: \Omega_\alpha \to
\mathbb{R}^d ~|~ \boldsymbol{w}=0~ \forall~ \boldsymbol{x}_\alpha \in
\Gamma^D_\alpha \}
The variational form for each body :math:`\alpha` is given as
.. math::
\int_{\Omega_\alpha}\boldsymbol{\sigma}[\boldsymbol{u}_\alpha]:\boldsymbol{\epsilon}[\boldsymbol{w}_\alpha]~d\Omega_\alpha
=
\int_{\Omega_\alpha}\boldsymbol{b}_\alpha.\boldsymbol{w}_\alpha~d\Omega_\alpha +
\int_{\Gamma^C_\alpha}\boldsymbol{T}_\alpha.\boldsymbol{w}_\alpha~d\Gamma_\alpha +
\int_{\Gamma^N_\alpha}\boldsymbol{T}_\alpha^D.\boldsymbol{w}_\alpha~d\Gamma^N_\alpha
In equilibrium state, following Newton's :math:`3^{rd}` law, it can be
stated the forces exerted by two bodies along :math:`\Gamma^C_\alpha`
are equal and opposite:
.. math::
\boldsymbol{T}_1~d\Gamma^C_1 = - \boldsymbol{T}_2~d\Gamma^C_2
This allows to replace the two integrals over contact surfaces
$\Gamma^C_\alpha$ with a single integral over any one of the surfaces:
.. math::
\int_\alpha
\boldsymbol{T}_\alpha.\delta\boldsymbol{u}_\alpha~d\Gamma^C_\alpha &=
\int_{\Gamma^C_1}\boldsymbol{T}_1\delta\boldsymbol{u}_1~d\Gamma^C_1 +
\int_{\Gamma^C_2} \boldsymbol{T}_2\delta\boldsymbol{u}_2~d\Gamma^C_2 \\ &=
\int_{\Gamma^C_1} \boldsymbol{T}_1(\delta\boldsymbol{u}_1 -
\delta\boldsymbol{u}_2)~d\Gamma^C_1
The contact traction :math:`\boldsymbol{T}_1` can be decomposed into
its normal and tangential components as:
.. math::
\boldsymbol{T}_\alpha = \boldsymbol{T}^n + \boldsymbol{T}^t
= \sigma_n\boldsymbol{n}+ \boldsymbol{T}^t
where :math:`\boldsymbol{T}^n` is the component along the normal
vector :math:`\boldsymbol{n}` and :math:`\boldsymbol{T}^t` is the
component tangential to :math:`\boldsymbol{n}` developed due to the
friction along the surfaces. Upon contact , the normal pressure
:math:`\sigma_n` associated to :math:`\boldsymbol{T}^n` must be
compressive to preclude the interpenetration of bodies. In general, if
a point is not in contact :math:`g > 0`, then :math:`\sigma_n=0` and
in contact :math:`\sigma_n < 0`. This leads to the non-penetration
condition:
.. math::
\sigma_n g = 0
The above set of conditions care called *Hertz-Signorini-Moreau* or
*Karush-Kuhn-Tucker* condition given as:
.. math::
g \geq 0, \quad \sigma_n \leq 0 \quad g.\sigma_n = 0
The tangential component of the contact traction is defined as :
.. math::
\boldsymbol{T}_t = (\boldsymbol{I} - \boldsymbol{n} \otimes \boldsymbol{n})\boldsymbol{\sigma}
where :math:`\boldsymbol{\sigma}` is the Cauchy stress tensor and
$\boldsymbol{n}$ is the outward normal at
:math:`\boldsymbol{\rho}`. The direction of tangential traction,
:math:`\boldsymbol{s}` is determined by the relative sliding velocity
:math:`\boldsymbol{v}_t` of the point :math:`\boldsymbol{r}` and its
projection point :math:`\boldsymbol{\rho}` in contact and is given as:
.. math::
\boldsymbol{s} = \begin{cases} \dfrac{\boldsymbol{v}_t}{\|
\boldsymbol{v}_t \|}, & \text{ if } \| \boldsymbol{v}_t\| > 0 \\ &
\\ 0, & \text{ if } \| \boldsymbol{v}_t\| = 0 \end{cases}
According to the experimental observations of Amontons
and~\cite{coulomb}, in presence of friction, the interface develops a
frictional strength which governs the sliding between them and thus
constrains the tangential contact. In Akantu implementation, we
restrict to the classical non-associated Coulomb's friction
law~\citep{coulomb} which is widely used in many physical and
engineering applications. The Coulomb's friction law, as a first-order
approximation, states that the frictional strength is proportional to
the normal pressure:
.. math::
\sigma_{fric} = \mu |\sigma_n|
where :math:`\mu` is coefficient of friction between interfaces. If
the tangential traction :math:`||\boldsymbol{T}^t||` developed is
below the frictional strength, the relative tangential sliding is zero
:math:`i.e.~\boldsymbol{v}_t = 0` :
.. math::
||\boldsymbol{T}^t|| < \mu| \sigma_n |, \quad \boldsymbol{v}_t=0
The above equation denotes a *stick state*. As soon as the tangential
stress reaches the frictional strength, the two surfaces start
slipping relative to each other :math:`i.e.~\boldsymbol{v}_t > 0`. The
slipping of the surfaces ensures that the tangential stress does not
exceeds the frictional strength, :math:`||\boldsymbol{\sigma}_t||
-\mu|\sigma_n| = 0`. This definition of *slip state* is defined as:
.. math::
||\boldsymbol{\sigma}_t|| -\mu|\sigma_n| = 0, \quad
||\boldsymbol{v}_t|| > 0
Similar to *Karush-Kuhn-Tucker* condition for normal contact, the
above conditions formulate the necessary conditions for tangential
contact:
.. math::
||\boldsymbol{v}_t|| \geq 0, \quad ||\boldsymbol{T}^t||
-\mu|\sigma_n| = 0, \quad ||\boldsymbol{v}_t||
\Big(||\boldsymbol{T}^t|| -\mu|\sigma_n| \Big) = 0
The above contact and frictional constraints are unilateral in nature
*i.e.* they do not behave symmetrically with respect to *gap function,
g*. This renders the balance of work as a variational inequality:
.. math::
\sum_{\alpha=1}^2
\int_{\Omega_\alpha}\boldsymbol{\sigma}[\boldsymbol{u}_\alpha]:\boldsymbol{\epsilon}[\boldsymbol{w}_\alpha]~d\Omega_\alpha
\geq \sum_{\alpha=1}^2 \Big \{
\int_{\Omega_\alpha}\boldsymbol{b}_\alpha.\boldsymbol{w}_\alpha~d\Omega_\alpha +
\int_{\Gamma^Ct_\alpha}\boldsymbol{T}_\alpha.\boldsymbol{w}_\alpha~d\Gamma_\alpha +
\int_{\Gamma^N_\alpha}\boldsymbol{T}_\alpha^D.\boldsymbol{w}_\alpha~d\Gamma_\alpha\Big
\}
which makes it a non-linear optimization problem. The strategy
employed (optimization techniques) to find the solution of variational
inequality depends on the choice of numerical framework employed to
solve the B.V.P.
To solve the minimization problem, FEM introduces the concept of
active set strategy to overcome the problem. In active set strategy,
it is assumed that at current solution step, the part of potential
contact zone :math:`\Gamma^C_1` that are in contact are known,
:math:`\Gamma^{C\star}_1 \subseteq \Gamma^C_1`. This
is achieved by first allowing the two bodies to interpenetrate and
finding the interpenetrated part of potential contact zone which will
denote the active set. Knowing the active set, transforms the
optimization problem to a variational equality where constraints are
imposed along the active part of contacting interface:
.. math::
\sum_{\alpha=1}^2
\int_{\Omega_\alpha}\boldsymbol{\sigma}[\boldsymbol{u}_\alpha]:\boldsymbol{\epsilon}[\delta\boldsymbol{u}_\alpha]~d\Omega_\alpha
= \sum_{\alpha=1}^2 \Big \{
\int_{\Omega_\alpha}\boldsymbol{b}_\alpha.\delta\boldsymbol{u}_\alpha~d\Omega_\alpha +
\int_{\Gamma^N_\alpha}\boldsymbol{T}_\alpha^D.\delta\boldsymbol{u}_\alpha~d\Gamma_\alpha\Big
\} \\
+ \int_{\Gamma^{C\star}_1
}\boldsymbol{T}_1(\delta\boldsymbol{u}_1 -
\delta\boldsymbol{u}_2)~d\Gamma^{C\star}_1
Thus, the resolution of contact problem in FEM requires two steps:
finding the active set along the contacting interface and then
imposing the contact constraints along the active set only. In the
following section, we describe how to employ the contact detection strategies
implemented within Akantu in order to find the active set and to compute contact forces.
Using the Contact Mechanics Model
----------------------------------
+`````````````````````````````````
The :cpp:class:`ContactMechanicsModel <akantu::ContactMechanicsModel>`
object solves the contact problem. An instance of
the class can be created like this::
ContactMechanicsModel contact(mesh, spatial_dimension);
while an existing mesh has been used (see \ref{sect:common:mesh}). To
intialize the model object::
contact.initFull(_analysis_method = _explicit_lumped_mass);
The contact mechanics model contains :cpp:class:`Arrays <akantu::Array>`:
:cpp:func:`gaps <akantu::ContactMechanicsModel::getgaps>`
contains the nodal interpenetrating value :math:`g` (positive for
interpenetration, zero by default after initialization)
:cpp:func:`normals <akantu::ContactMechanicsModel::getNormals>`
contains the normal vector at the slave nodes (zero by default
after initialization).
In Akantu, the possible contact between surfaces is divided into 3
categories.
- Physical Surfaces - The contact occurs between two pyhsically
defined boundaries/surfaces of a body.
- Cohesive Surfaces - The contact occurs between fracturing surfaces
created using :cpp:class:`SolidMechanicsModelCohesive
<akantu::SolidMechanicsModelCohesive>`.
- All Surfaces - The contact can occur between physical as well as
cohesive surfaces.
To select the contacting surfaces, one must define a
:cpp:class:`SurfaceSelector <akantu::SurfaceSelector>` of one of the
above defined types.
To define contact between Physical surfaces, an instance of
:cpp:class:`PhysicalSurfaceSelector <akantu::PhysicalSurfaceSelector>`
is created where the mesh object (see \ref{sect:common:mesh}) is
passed as an argument::
auto && surface_selector = std::make_shared<PhysicalSurface>(mesh);
To define contact between cohesive surfaces, an instance of
:cpp:class:`CohesiveSurfaceSelector <akantu::CohesiveSurfaceSelector>`
must be created. As the contact occurs between the cohesive facets,
therefore the mesh facet object is passed as an argument::
auto && surface_selector = std::make_shared<CohesiveSurface>(mesh.getMeshFacets());
To defind contact between physical and cohesive surfaces, an instance of
:cpp:class:`AllSurfaceSelector <akantu::AllSurfaceSelector>`
must be created. As the contact occurs between the cohesive facets,
therefore the mesh facet object is passed as an argument::
auto && surface_selector = std::make_shared<AllSurface>(mesh.getMeshFacets());
Once a surface selector is created it must be assigned to the
:cpp:class:`ContactDetector <akantu::ContactDetector>` class::
contact.getContactDetector().setSurfaceSelector(surface_selector);
-
+
+
+.. _sect-cmm-contact-detection:
Contact detection
'''''''''''''''''
-The contact detection algorithm can receive the a few parameters. It is possible to
+The contact detection algorithm can receive a few parameters. It is possible to
specify the master/slave surfaces with their string identifier. The geometrical projections
are performed with iterations which can be controlled as a classical optimization problem.
A typical detection configuration is given below:
.. code-block::
contact_detector [
type = explicit
master = contact_bottom
slave = contact_top
projection_tolerance = 1e-10
max_iterations = 100
extension_tolerance = 1e-5
]
Contact resolution
''''''''''''''''''
The contact resolution defines the surface tractions due to contact
both for normal and tangential contact. A typical configuration for a
penalization formulation is as follows:
.. code-block::
contact_resolution penalty_linear [
name = contact_top
mu = 0.0 # friction coefficient
epsilon_n = 4e5 # normal penalization
epsilon_t = 1e5 # friction penalization
is_master_deformable = false # when master is rigid => computational savings
]
+.. _sect-cmm-coupling-with-smm:
+
Coupling with :cpp:class:`SolidMechanicsModel <akantu::SolidMechanicsModel>`
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+````````````````````````````````````````````````````````````````````````````
To couple the
:cpp:class:`ContactMechancisModel<akantu::ContactMechanicsModel>`
contact mechanics model with
:cpp:class:`SolidMechanicsModel<akantu::SolidMechanicsModel>` a
dedicated coupler class :cpp:class:`CouplerSolidContact<akantu::CouplerSolidContact>` is provided.
When an instance of a coupler class is created, it automatically
creates the instances of solid mechanics model and contact mechanics
model. The two objects can be retrived from the coupler class.
.. code-block:: c++
CouplerSolidContact coupler(mesh);
auto & solid = coupler.getSolidMechanicsModel();
auto & contact = coupler.getContactMechanicsModel();
Simply initializing the coupler initializes the two models.
.. code-block:: c++
coupler.initFull( _analysis_method = _explicit_lumped_mass);
-However two set the material selector and the contact detector for the
+However to set the material selector and the contact detector for the
two models, one must set them using directly the instance of the two
model classes.
.. code-block:: c++
auto && selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names",solid);
solid.setMaterialSelector(selector);
.. code-block:: c++
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(mesh);
contact.getContactDetector().setSurfaceSelector(surface_selector);
The dumping fields/vectors belonging to the solid mechanics model and
contact mechanics model can directly be set through the coupler
class.
.. code-block:: c++
coupler.setBaseName("contact-explicit-dynamic");
coupler.addDumpFieldVector("displacement");
coupler.addDumpFieldVector("normal_force");
coupler.addDumpFieldVector("external_force");
coupler.addDumpFieldVector("internal_force");
coupler.addDumpField("gaps");
coupler.addDumpField("areas");
coupler.addDumpField("stress");
Finally to solve the two models :cpp:func:`solveStep
<akantu::CouplerSolidContact::solveStep>` function of coupler class must be
invoked.
.. code-block:: c++
coupler.solveStep();
Coupling with :cpp:class:`SolidMechanicsModelCohesive <akantu::SolidMechanicsModelCohesive>`
-'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+`````````````````````````````````````````````````````````````````````````````````````````````
To use the contact mechanics model with cohesive elements, one must use the
:cpp:class:`CouplerSolidCohesiveContact<akantu::CouplerSolidCohesiveContact>` to
coupler the :cpp:class:`ContactMechancisModel<akantu::ContactMechanicsModel>`
with
:cpp:class:`SolidMechanicsModelCohesive<akantu::SolidMechanicsModelCohesive>`.
The initialization and invocation of the functions are similar to
:cpp:class:`CouplerSolidContact<akantu::CouplerSolidContact>` except a few
changes.
.. code-block:: c++
solid = coupler.getSolidMechanicsModelCohesive();
While initializing the coupler, the nature of cohesive elements
(extrinsic/intrinsic) should need to be passed.
.. code-block:: c++
coupler.initFull( _analysis_method = _explicit_lumped_mass, _is_extrinsic=true);
To ensure that cohesive elements break during an explicit insertion, one must
call the function :cpp:func:`checkCohesiveStress()
<akantu::SolidMechanicsModelCohesive::checkCohesiveStress>` after
:cpp:func:`solveStep() <akantu::SolidMechanicsModelCohesive::solveStep>`.
.. code-block:: c++
coupler.solveStep();
solid.checkCohesiveStress();
diff --git a/doc/dev-doc/manual/heattransfermodel.rst b/doc/dev-doc/manual/diffusion.rst
similarity index 86%
rename from doc/dev-doc/manual/heattransfermodel.rst
rename to doc/dev-doc/manual/diffusion.rst
index 9f6eefb89..705c78d18 100644
--- a/doc/dev-doc/manual/heattransfermodel.rst
+++ b/doc/dev-doc/manual/diffusion.rst
@@ -1,169 +1,181 @@
-Heat Transfer Model
-===================
+.. _sect-dm:
+
+Diffusion 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
+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
+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.
+The diffusion model is meant as a base to implement different diffusive processes, heat diffusion, chemical diffusion, simple flow problems, etc. Currently only one of this physics is implemented, the heat diffusion, in a model named HeatTransferModel
+
+.. _sect-dm-using:
+
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}%]
+ constitutive_law heat_diffusion [
+ name = %\emph{XXX}%
+ 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.
+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.
+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 (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/extra.rst b/doc/dev-doc/manual/extra.rst
new file mode 100644
index 000000000..d46b839f6
--- /dev/null
+++ b/doc/dev-doc/manual/extra.rst
@@ -0,0 +1,6 @@
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/doc/dev-doc/manual/fe_engine.rst b/doc/dev-doc/manual/fe_engine.rst
deleted file mode 100644
index 34779e141..000000000
--- a/doc/dev-doc/manual/fe_engine.rst
+++ /dev/null
@@ -1,233 +0,0 @@
-FEEngine
-========
-
-The :cpp:class:`FEEngine<akantu::FEEngine>` interface is dedicated to handle the
-finite-element approximations and the numerical integration of the weak form. As
-we will see in Chapter :doc:`./solidmechanicsmodel`,
-:cpp:class:`Model<akantu::Model>` creates its own
-:cpp:class:`FEEngine<akantu::FEEngine>` object so the explicit creation of the
-object is not required.
-
-Mathematical Operations
------------------------
-
-Using the :cpp:class:`FEEngine<akantu::FEEngine>` object, one can compute a interpolation,
-an integration or a gradient.A simple example is given below:
-
-.. code-block:: c++
-
- // having a FEEngine object
- auto fem = std::make_unique<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,
- 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,
- 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, ElementType type);
-
-
-Another example below shows how to integrate stress and strain fields over
-elements assigned to a particular material:
-
-.. code-block:: c++
-
- UInt sp_dim{3}; // spatial dimension
- UInt m{1}; // material index of interest
- const auto type{_tetrahedron_4}; // element type
-
- // get the stress and strain arrays associated to the material index m
- const auto & strain_vec = model.getMaterial(m).getGradU(type);
- const auto & stress_vec = model.getMaterial(m).getStress(type);
-
- // get the element filter for the material index
- const auto & 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);
-
-
-.. _sec-elements:
-
-Elements
---------
-
-The base for every Finite-Elements computation is its mesh and the elements that
-are used within that mesh. The element types that can be used depend on the
-mesh, but also on the dimensionality of the problem (1D, 2D or 3D). In
-``Akantu``, several iso-parametric Lagrangian element types are supported (and
-one serendipity element). Each of these types is discussed in some detail below,
-starting with the 1D-elements all the way to the 3D-elements. More detailed
-information (shape function, location of Gaussian quadrature points, and so on)
-can be found in Appendix app:elements.
-
-Iso-parametric Elements
-.......................
-
-1D
-````
-
-There are two types of iso-parametric elements defined in 1D. These element
-types are called :cpp:enumerator:`_segment_2 <akantu::_segment_2>` and
-:cpp:enumerator:`_segment_3 <akantu::_segment_3>`, and are depicted
-schematically in :numref:`fig-elements-1D`. Some of the basic properties of
-these elements are listed in :numref:`tab-elements-1D`.
-
-.. _fig-elements-1D:
-.. figure:: figures/elements/segments.svg
- :align: center
-
- Schematic overview of the two 1D element types in ``Akantu``. In each
- element, the node numbering as used in ``Akantu`` is indicated and also the
- quadrature points are highlighted (gray circles).
-
-
-.. _tab-elements-1D:
-.. csv-table:: Some basic properties of the two 1D iso-parametric elements in ``Akantu``
- :header: "Element type", "Order", "#nodes", "#quad points"
-
- ":cpp:enumerator:`_segment_2 <akantu::_segment_2>`", "linear", 2, 1
- ":cpp:enumerator:`_segment_3 <akantu::_segment_3>`", "quadratic", 3, 2
-
-2D
-````
-
-There are four types of iso-parametric elements defined in 2D. These element
-types are called :cpp:enumerator:`_triangle_3 <akantu::_triangle_3>`,
-:cpp:enumerator:`_triangle_6 <akantu::_triangle_6>`,
-:cpp:enumerator:`_quadrangle_4 <akantu::_quadrangle_4>` and
-:cpp:enumerator:`_quadrangle_8 <akantu::_quadrangle_8>`, and all of them are
-depicted in :numref:`fig-elements-2D`. As with the 1D elements, some of the most
-basic properties of these elements are listed in :numref:`tab-elements-2D`. It
-is important to note that the first element is linear, the next two quadratic
-and the last one cubic. Furthermore, the last element type (``_quadrangle_8``)
-is not a Lagrangian but a serendipity element.
-
-.. _fig-elements-2D:
-.. figure:: figures/elements/elements_2d.svg
- :align: center
-
- Schematic overview of the four 2D element types in ``Akantu``. In each
- element, the node numbering as used in ``Akantu`` is indicated and also the
- quadrature points are highlighted (gray circles).
-
-
-.. _tab-elements-2D:
-.. csv-table:: Some basic properties of the 2D iso-parametric elements in ``Akantu``
- :header: "Element type", "Order", "#nodes", "#quad points"
-
- ":cpp:enumerator:`_triangle_3 <akantu::_triangle_3>`", "linear", 3, 1
- ":cpp:enumerator:`_triangle_6 <akantu::_triangle_6>`", "quadratic", 6, 3
- ":cpp:enumerator:`_quadrangle_4 <akantu::_quadrangle_4>`", "linear", 4, 4
- ":cpp:enumerator:`_quadrangle_8 <akantu::_quadrangle_8>`", "quadratic", 8, 9
-
-3D
-````
-
-In ``Akantu``, there are three types of iso-parametric elements defined in 3D.
-These element types are called :cpp:enumerator:`_tetrahedron_4
-<akantu::_tetrahedron_4>`, :cpp:enumerator:`_tetrahedron_10
-<akantu::_tetrahedron_10>` and :cpp:enumerator:`_hexadedron_8
-<akantu::_hexadedron_8>`, and all of them are depicted schematically in
-:numref:`fig-elements-3D`. As with the 1D and 2D elements some of the most basic
-properties of these elements are listed in :numref:`tab-elements-3D`.
-
-.. _fig-elements-3D:
-.. figure:: figures/elements/elements_3d.svg
- :align: center
-
- Schematic overview of the three 3D element types in ``Akantu``. In each
- element, the node numbering as used in ``Akantu`` is indicated and also the
- quadrature points are highlighted (gray circles).
-
-.. _tab-elements-3D:
-.. csv-table:: Some basic properties of the 3D iso-parametric elements in ``Akantu``
- :header: "Element type", "Order", "#nodes", "#quad points"
-
- ":cpp:enumerator:`_tetrahedron_4 <akantu::_tetrahedron_4>`", "linear", 4, 1
- ":cpp:enumerator:`_tetrahedron_10 <akantu::_tetrahedron_10>`", "quadratic", 10, 4
- ":cpp:enumerator:`_hexadedron_8 <akantu::_hexadedron_8>`", "cubic", 8, 8
-
-Cohesive Elements
-.................
-
-The cohesive elements that have been implemented in ``Akantu`` are based
-on the work of Ortiz and Pandolfi :cite:`ortiz1999`. Their main
-properties are reported in :numref:`tab-coh-cohesive_elements`.
-
-.. _fig-smm-coh-cohesive2d:
-.. figure:: figures/elements/cohesive_2d_6.svg
- :align: center
-
- Cohesive element in 2D for quadratic triangular elements T6.
-
-.. _tab-coh-cohesive_elements:
-.. csv-table:: Some basic properties of the cohesive elements in ``Akantu``.
- :header: "Element type", "Facet type", "Order", "#nodes", "#quad points"
-
- ":cpp:enumerator:`_cohesive_1d_2 <_cohesive_1d_2>`", ":cpp:enumerator:`_point_1 <akantu::_point_1>`", "linear", 2, 1
- ":cpp:enumerator:`_cohesive_2d_4 <akantu::_cohesive_2d_4>`", ":cpp:enumerator:`_segment_2 <akantu::_segment_2>`", "linear", 4, 1
- ":cpp:enumerator:`_cohesive_2d_6 <akantu::_cohesive_2d_6>`", ":cpp:enumerator:`_segment_3 <akantu::_segment_3>`", "quadratic", 6, 2
- ":cpp:enumerator:`_cohesive_3d_6 <akantu::_cohesive_3d_6>`", ":cpp:enumerator:`_triangle_3 <akantu::_triangle_3>`","linear", 6, 1
- ":cpp:enumerator:`_cohesive_3d_12 <akantu::_cohesive_3d_12>`", ":cpp:enumerator:`_triangle_6 <akantu::_triangle_6>`", "quadratic", 12, 3
-
-
-Structural Elements
-...................
-
-Bernoulli Beam Elements
-```````````````````````
-
-These elements allow to compute the displacements and rotations of
-structures constituted by Bernoulli beams. ``Akantu`` defines them for
-both 2D and 3D problems respectively in the element types
-:cpp:enumerator:`_bernoulli_beam_2 <akantu::_bernoulli_beam_2>` and :cpp:enumerator:`_bernoulli_beam_3 <akantu::_bernoulli_beam_3>`. A
-schematic depiction of a beam element is shown in
-:numref:`fig-elements-bernoulli` and some of its properties are
-listed in :numref:`tab-elements-bernoulli`.
-
-.. note::
- Beam elements are of mixed order: the axial displacement is
- linearly interpolated while transverse displacements and rotations
- use cubic shape functions.
-
-.. _fig-elements-bernoulli:
-.. figure:: figures/elements/bernoulli_2.svg
- :align: center
-
- Schematic depiction of a Bernoulli beam element (applied to 2D and
- 3D) in ``Akantu``. The node numbering as used in ``Akantu`` is
- indicated, and also the quadrature points are highlighted (gray
- circles).
-
-.. _tab-elements-bernoulli:
-.. csv-table:: Some basic properties of the beam elements in ``Akantu``
- :header: "Element type", "Dimension", "# nodes", "# quad. points", "# d.o.f."
-
- ":cpp:enumerator:`_bernoulli_beam_2 <akantu::_bernoulli_beam_2>`", "2D", 2, 3, 6
- ":cpp:enumerator:`_bernoulli_beam_3 <akantu::_bernoulli_beam_3>`", "3D", 2, 3, 12
diff --git a/doc/dev-doc/manual/figures/examples/cohesive_extrinsic.gif b/doc/dev-doc/manual/figures/examples/cohesive_extrinsic.gif
new file mode 100644
index 000000000..2d75fd400
Binary files /dev/null and b/doc/dev-doc/manual/figures/examples/cohesive_extrinsic.gif differ
diff --git a/doc/dev-doc/manual/figures/examples/cohesive_extrinsic_ig_tg.gif b/doc/dev-doc/manual/figures/examples/cohesive_extrinsic_ig_tg.gif
new file mode 100644
index 000000000..f332f6d41
Binary files /dev/null and b/doc/dev-doc/manual/figures/examples/cohesive_extrinsic_ig_tg.gif differ
diff --git a/doc/dev-doc/manual/figures/examples/cohesive_intrinsic.png b/doc/dev-doc/manual/figures/examples/cohesive_intrinsic.png
new file mode 100644
index 000000000..de2d30b1d
Binary files /dev/null and b/doc/dev-doc/manual/figures/examples/cohesive_intrinsic.png differ
diff --git a/doc/dev-doc/manual/getting_started.rst b/doc/dev-doc/manual/getting_started.rst
index cd1b7e11c..29357926e 100644
--- a/doc/dev-doc/manual/getting_started.rst
+++ b/doc/dev-doc/manual/getting_started.rst
@@ -1,577 +1,281 @@
Getting Started
===============
Contributing
------------
Contributing new features, bug fixes
````````````````````````````````````
Any contribution is welcome, we are trying to follow a `gitflow <https://nvie.com/posts/a-successful-git-branching-model/>`_ workflow, so the project `developers` can create branches named `features/<name of my feature>` or `bugfixes/<name of the fix>` directly in the main `akantu` repository.
External fellows can `Fork <https://gitlab.com/akantu/akantu/-/forks/new>`_ the project.
In both cases the modifications have to be submitted in the form of a `Merge Request <https://gitlab.com/akantu/akantu/-/merge_requests/new>`_.
Asking for help, reporting issues
`````````````````````````````````
If you want to ask for help concerning Akantu's compilation, usage or problem with the code do not hesitate to open an `Issue <https://gitlab.com/akantu/akantu/-/issues/new>`_ on gitlab. If you want to contribute and don't know where to start, you are also invited to open an issue.
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 (pre-processor and Spirit)
- - zlib
- Eigen3 (if not present the build system will try to download it)
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)
On ``.deb`` based Linux systems
"""""""""""""""""""""""""""""""
.. code-block:: bash
- > sudo apt install cmake libboost-dev zlib1g-dev gmsh libeigen3-dev
+ > sudo apt install cmake libboost-dev gmsh libeigen3-dev
# For parallel
> sudo apt install mpi-default-dev libmumps-dev libscotch-dev
# For sequential
> sudo apt install libmumps-seq-dev
Using ``conda``
"""""""""""""""
This works only for sequential computation since `mumps` from conda-forge is compiled without MPI support:
.. code-block:: bash
> conda create -n akantu
> conda activate akantu
> conda install boost cmake
> conda install -c conda-forge mumps
Using ``homebrew``
""""""""""""""""""
.. code-block:: bash
> brew install gcc
> brew install boost@1.76
> brew tap brewsci/num
> brew install brewsci-mumps --without-brewsci-parmetis
If it does not work you can edit url to http://graal.ens-lyon.fr/MUMPS/MUMPS_5.3.5.tar.gz using the command:
.. code-block:: bash
> brew edit brewsci/num
Configuring and compilation
```````````````````````````
`Akantu` is a `CMake <https://cmake.org/>`_ project, so to configure it, you can follow the usual way:
.. code-block:: bash
> cd akantu
> mkdir build
> cd build
> ccmake ..
[ Set the options that you need ]
> make
> make install
On Mac OS X with ``homebrew``
"""""""""""""""""""""""""""""
-You will need to specify the compiler explicitly::
+You will need to specify the compiler explicitly
.. code-block:: bash
- > CC=gcc-12 CXX=g++-12 FC=gfortran-12 cmake ..
+ > CC=gcc-12 CXX=g++-12 FC=gfortran-12 cmake ..
-Considering that ``homebrew` is installed in ``/opt/homebrew``
+Considering that `homebrew` is installed in ``/opt/homebrew``
Define the location of the ``Scotch`` library path:
.. code-block:: bash
> cmake .. -DSCOTCH_LIBRARY="/opt/homebrew/lib/libscotch.dylib;/opt/homebrew/lib/libscotcherr.dylib;/opt/homebrew/lib/libscotcherrexit.dylib"
Specify path to all ``MUMPS`` libraries:
.. code-block:: bash
> cmake .. -DMUMPS_DIR=/opt/homebrew/opt/brewsci-mumps
In case the above does not work, specify the ``MUMPS`` path manually using (e.g.):
.. code-block:: bash
> cmake .. -DMUMPS_LIBRARY_COMMON=/opt/homebrew/opt/brewsci-mumps/lib/libmumps_common.dylib
If compilation does not work change the path of the failing libraries to brew downloads in `/opt/homebrew/`.
Using the python interface
--------------------------
You can install ``Akantu`` using pip, this will install a pre-compiled version, this works only on Linux machines for now::
> 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 Renku.
The tutorials are currently available: |renku|
.. |renku| image:: https://user-content.gitlab-static.net/52a4794df1236b248c8fc870bd74e9d787c0e2cb/68747470733a2f2f72656e6b756c61622e696f2f72656e6b752d62616467652e737667
:target: https://renkulab.io/projects/guillaume.anciaux/akantu-tutorials/sessions/new?autostart=1
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
+The :cpp:func:`initialize <akantu::initialize>` function takes the text input
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
+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
+ cmake_minimum_required(VERSION 3.12.0)
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
+Otherwise ``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``
+``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. ::
+file extension is used, the mesh type has to be specified.
+
+.. code-block:: c++
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:`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:`Int
<akantu::Int>` data named ``tag_1``.
-Using Arrays
-------------
+Running parallel simulation
+---------------------------
-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;
- 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:
+In order to run distributed memory simulation a few extra steps have to be taken.
+The mesh as to be distributed
.. 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 */
-
+ const auto & comm = Communicator::getStaticCommunicator();
+ if (comm.whoAmI() == 0) { // MPI rank
+ // Read the mesh
+ mesh.read("square_2d.msh");
+ }
+ mesh.distribute();
-The ``NodeGroup`` object
-''''''''''''''''''''''''
+All the communications and the distribution of the mesh and associated data will
+be taken care automatically.
-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:
+Currently the mesh decomposition is handled by the `Scotch
+<https://gitlab.inria.fr/scotch/scotch>`_ library. Which means if needed you
+could define different edge and vertex weights
.. 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);
- }
-
+ mesh.distribute(_edge_weight_function =
+ [](auto &&, auto &&) { return 1; },
+ _vertex_weight_function =
+ [](auto &&) { return 1; });
-The ``ElementGroup`` object
-'''''''''''''''''''''''''''
+The `vertex` weights correspond to the computational cost of the elements, and
+the `edge` weights relates to the cost of communications between 2 elements.
-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++
+To run the simulation you will need to use a runner appropriate to your machine,
+like `mpirun`, `srun`, `arun`, etc.
- auto & group = mesh.createElementGroup("XpositiveElement");
- Vector<Real> barycenter(spatial_dimension);
+.. code-block:: sh
- for_each_element(mesh, [&](auto && element) {
- mesh.getBarycenter(element, barycenter);
- if (barycenter(_x) > 0.) { group.add(element); }
- });
+ $ mpirun -np 4 ./my_simulation
diff --git a/doc/dev-doc/manual/models.rst b/doc/dev-doc/manual/models.rst
new file mode 100644
index 000000000..d5221f9aa
--- /dev/null
+++ b/doc/dev-doc/manual/models.rst
@@ -0,0 +1,19 @@
+.. _sect-models:
+
+Models
+======
+
+.. include:: models_commons.rst
+
+.. include:: solidmechanicsmodel.rst
+.. include:: contactmechanicsmodel.rst
+
+Models [Unstable]
+=================
+
+This models are implemented for some research purposes but might not have the
+same level of stability or tests than the models that are not marked unstable.
+
+.. include:: diffusion.rst
+.. include:: phasefieldmodel.rst
+.. include:: structuralmechanicsmodel.rst
diff --git a/doc/dev-doc/manual/models_commons.rst b/doc/dev-doc/manual/models_commons.rst
new file mode 100644
index 000000000..e69de29bb
diff --git a/doc/dev-doc/manual/new-constitutive-laws.rst b/doc/dev-doc/manual/new-constitutive-laws.rst
index 300b9f4e3..92962112b 100644
--- a/doc/dev-doc/manual/new-constitutive-laws.rst
+++ b/doc/dev-doc/manual/new-constitutive-laws.rst
@@ -1,373 +1,375 @@
+.. _sect-smm-ncl:
+
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__
+ #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 (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(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__
+ #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/phasefieldmodel.rst b/doc/dev-doc/manual/phasefieldmodel.rst
index 1935beb16..6dc660ef8 100644
--- a/doc/dev-doc/manual/phasefieldmodel.rst
+++ b/doc/dev-doc/manual/phasefieldmodel.rst
@@ -1,265 +1,265 @@
PhaseField Model
-================
+----------------
The phasefield model is a specific implementation of
:cpp:class:`Model <akantu::Model>` interface to handle brittle fracture
for infinitesimal strains.
Theory
-------
+``````
The variational formulation of brittle fracture was first proposed by
Francfort and Marigo:cite:`franc` so as to overcome the shortcomings
of Griffith's criteria. The approach used by Francfort and Margio for
variational formulation is based on the principle of global minimality
of total energy. Similar to Griffith's work, they define a surface
energy corresponding to the discontinuity :math:`\Gamma` as
.. math::
\Phi_{s}(\Gamma) = \int\limits_{\Gamma}\mathcal{G}_cd\mathcal{H}^{d-1}(\Gamma)
where :math:`\mathcal{H}^{d-1}` is d-1 dimensional Hausdroff measure
which is surface measure for smooth hypersurfaces. the material
behavior is considered to be linearly elastic with small strains
throughout the body. Based on these assumptions the elastic energy of
the body is defined as
.. math::
\Phi_e(\Gamma,u) = \int\limits_{\Omega_{p}}\psi(\boldsymbol{\epsilon}(u))d\Omega
where :math:`\psi` is elastic energy density and it is given as a
function of strain as
.. math::
\psi_e(\boldsymbol{\epsilon}) = \dfrac{1}{2}\lambda(\text{tr}(\boldsymbol{\epsilon}))^{2}+\mu\boldsymbol{\epsilon}:\boldsymbol{\epsilon}
Exponential phasefield law
''''''''''''''''''''''''''
Bourdin et. al.:cite:`bourdin` in their work proposed a regularized
version of variational formulation where a scalar field variable
:math:`d(\vec{x},t)` is used to represent crack. This scalar field
variable approximates the sharp crack topology by taking value 1 at
crack location and smoothly diffusing into value 0 away from the
crack. \figref{fig:diffusive_topology} shows both sharp crack topology
and an approximated regularized crack topology for one-dimensional
case.
The strong form of the phasefield can be expressed as
.. math::
2(1-d)\mathcal{H} - \dfrac{G_c}{l_0}(d-l_0^2d) = 0
\nabla d . \boldsymbol n = 0
Using the PhaseField Model
---------------------------
+``````````````````````````
The :cpp:class:`PhaseFieldModel <akantu::PhaseFieldModel>` object
solves the strong form using an inplicit solver. An instance of the
class can be created like this::
PhaseFieldModel phase(mesh, spatial_dimension);
while ans existing mesh has been used (see \ref{sect:common:mesh}). To
intialize the model object::
phase.initFull();
Currently, implicit solver is defined for the phasefield model and no
explicit solver is implemented in Akantu. Furthermore, By default, the
implicit solver defined is of linear type. One can change the linear
solver to a non-linear by initiating a new solver type.
The phasefield model contains :cpp:class:`Arrays <akantu::Array>`:
:cpp:func:`damage <akantu::PhaseFieldModel::getDamage>`:
contains the nodal damage :math:`d` (zero by default after the
initialization)
:cpp:func:`blocked_dofs <akantu::PhaseFieldModel::getBlockedDOFs>`
contains a Boolean value specifying whether the damage at a node
is to be blocked or not. A Dirichlet boundary condition can be
prescribed by setting the **blocked_dofs** value of damage to
``true``. The **damage** ais computed for all nodes where the
**blocked_dofs** value is set to ``false``. For the remaining
nodes, the imposed values (zero by default after initialization)
are kept.
:cpp:func:`internal_force <akantu::PhaseFieldModel::getInternalForce>`
contains the driving force responsible for the crack to nucelate
or propagate.
Currently, the phasefield model uses a exponential shaped scalar
field variable :math:`d(\vec{x}, t)` to approximate the sharp crack
topology. A Phasefield variable thus requires a length scale
parameter :math:`l_0` to control the width of the diffusive crack
topology along with the material parameters such as elastic modulus,
poisson's ratio, critical energy release rate.
The data input file provides the parameters for the exponential
phasefield law as follows:
.. code-block::
phasefield exponential [
name = plate
E = 210.0
nu = 0.3
gc = 5e-3
l0 = 0.1
]
:cpp:class:`PhaseFieldModel<akantu::PhaseFieldModel>` can handle
phasefield laws for multiple materials. To define so:
.. code-block::
phasefield exponential [
name = hard
E = 210.0
nu = 0.3
gc = 5e-3
l0 = 0.1
]
phasefield exponential [
name = soft
E = 21.0
nu = 0.3
gc = 5e-5
l0 = 0.1
]
In order to assign correct phasefield variable properties based on the
names of region as defined in mesh file,
:cpp:class:`MeshDataPhaseFieldSelector
<akantu::MeshDataPhaseFieldSelector>` must be set as phasefield
selector::
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
For the crack to nucleate or propagate, phasefield model requires
strain measure at each quadrature point. The strain measure computed
from solid mechanics model is provided to the phasefield
model. Similarly, damage value computed at each quadrature point by
the phasefield model is provided to the solid mechanics model. This
damage is thus used to degrade the the elastic strain energy. To do
so, a new material which is a specific implementation of
:cpp:class:`MaterialDamage <akantu::MaterialDamage>` is defined for
solid mechanics model. The governing equation is given as
.. math::
\boldsymbol \sigma = ((1-d)^2 + \eta)\dfrac{\psi}{\boldsymbol \epsilon}
where :math:`\psi` is the elastic energy and :math:`\eta` is a
numerical parmaeter avoid numerical difficulties due to full
degradation of elastic energy for fully broken state. The material
properties are thus provided in the input data filled as:
.. code-block::
material phasefield [
name = hard
rho = 1.
E = 210.0
nu = 0.3
eta = 0.0
Plane_Stress = false
]
material phasefield [
name = soft
rho = 1.
E = 21.0
nu = 0.3
eta = 0.0
Plane_Stress = false
]
To simplify the execution of phasefield model coupled with
solidmechanis model, a special class
:cpp:class:`CouplerSolidPhaseField<akantu::CouplerSolidPhaseField>` is
provided.
Coupling Phase Field Model and Solid Mechanics Model
''''''''''''''''''''''''''''''''''''''''''''''''''''
A dedicated coupler class :cpp:class:`CouplerSolidPhaseField
<akantu::CouplerSolidPhaseField>` is defined in Akantu to ease the
coupling of the two models.
When an instance of a Coupler class is created, it automatically
creates the instances of solid mechanics model and phasefield
model. The two objects can be retrived from the coupler class.
.. code-block:: c++
CouplerSolidPhaseField coupler(mesh);
auto & phase = coupler.getPhaseFieldModel();
auto & solid = coupler.getSolidMechanicsModel();
The two objects must be used to define the solver type and apply
boundary conditions.
.. code-block:: c++
solid.initFull(_analysis_method = _explicit_lumped_mass);
phase.initFull(_analysis_method = _static);
The whole process of coupling the two models at a given time step is
made easy by the :cpp:func:`solve <akantu::CouplerSolidPhaseField::solve>`
function of coupler class.
.. code-block:: c++
coupler.solve(<solver_id_for_solid_model>, <solver_id_for_phasefield_model>);
Staggered scheme
-----------------
+````````````````
To solve the solid mechanics model and phasefield model, staggered
scheme is implemented. In staggered scheme, at current time step first
solid mechanics model is solved assuming the damage values from the
previous time step. The strain thus computed are passed to the
phasefield model and now, phasefield model is solved for the damage
variable. At each iteration step, convergence in displacement and
damage is checked for. If convergence is not reached, the combined
newton-raphson iteration continues.
To illustrate the staggered scheme solution of phasefield model, one
can refere to the examples provided for the phasefield model. Two
examples provided are for static `phasefield-static.py` and dynamic
crack propgation `phasefield-dynamic.py`.
For the static problem, both the solid mechanics model and the
phsefield model are solved using alinear implicit solver. Convergence
in value of both displacement as well as damage is checked at each
loading step.
In case of the dynamic problem, solid mechanics model is solved
dynamically using an explicit solver and the phasefield model is
solved using a linear implcit solver. In this sceanrio, the staggered
scheme doesnot check for any convergence. Below is the crack
propagation observed for the dyanmic problem.
.. _fig-phasefieldmodel-dynamic:
.. figure:: figures/phasefield-dynamic.png
:align: center
Dynamic crack propagation using phasefield model
.. LocalWords: phasefield SolidMechanics PhaseField akantu cpp
diff --git a/doc/dev-doc/manual/solidmechanicsmodel.rst b/doc/dev-doc/manual/solidmechanicsmodel.rst
index 236216a69..0c8eb6465 100644
--- a/doc/dev-doc/manual/solidmechanicsmodel.rst
+++ b/doc/dev-doc/manual/solidmechanicsmodel.rst
@@ -1,883 +1,888 @@
.. _sect-smm:
-Solid Mechanics Model
-=====================
+Solid Mechanics Model / Solid Mechanics Model Cohesive
+------------------------------------------------------
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 (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 (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 }}
+ \sigma_\st{eff} > \sigma_\st{c} \quad\text {with} \quad \sigma_\st{eff} = \sqrt{\sigma_\st{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`).
+in which :math:`\sigma_\st{n}` is the tensile normal traction and $\tau$ the
+resulting tangential one (:numref:`fig-smm-coh-insertion`).
+
+.. _sect-smm-extrinsic-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
]
]
-
+``cohesive_surfaces`` defines are the physical surfaces defined in the mesh
+(``Curves`` in 1D and ``Surfaces`` in 2D) on which the insertion is allowed,
+``cohesive_zones`` are the physical volumes in which the insertion is allowed
+(``Surfaces`` in 2D and ``Volumes`` in 3D).
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
+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
+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 (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 (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 1da5dd206..d1087c70d 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 (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/dev-doc/requirements.txt b/doc/dev-doc/requirements.txt
index 0b39a9070..9eab0b57e 100644
--- a/doc/dev-doc/requirements.txt
+++ b/doc/dev-doc/requirements.txt
@@ -1,7 +1,10 @@
+breathe==4.34.0
+gitpython==3.1.30
+jinja2==3.1.2
+myst-parser==0.18.1
+sphinx-copybutton==0.4.0
+sphinx-rtd-theme==1.3.0
+sphinx==5.3.0
+sphinxcontrib-bibtex==2.5.0
+sphinx-toolbox==3.5.0
urllib3<2
-sphinx==3.4.3
-sphinx-rtd-theme==0.5.2
-sphinxcontrib-bibtex==2.3.0
-breathe==4.30.0
-jinja2==3.0.1
-gitpython==3.1.18
diff --git a/doc/dev-doc/tutorials.rst b/doc/dev-doc/tutorials.rst
new file mode 100644
index 000000000..3342663b8
--- /dev/null
+++ b/doc/dev-doc/tutorials.rst
@@ -0,0 +1,10 @@
+Tutorials
+=========
+
+In addition to the examples, we propose a list of tutorials that can be tested
+online without having to install Akantu locally.
+
+The tutorials are available on `Renku IO
+<https://renkulab.io/projects/guillaume.anciaux/akantu-tutorials/sessions/new?autostart=1>`_
+
+The code of the tutorials can be found on GitLab in `akantu/tutorials <https://gitlab.com/akantu/tutorials>`_
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index cc1bdad9c..bc3513939 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,43 +1,29 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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_example(new_material "Example on how to add a new material in Akantu" PACKAGE core)
-add_example(boundary_conditions "Example on hoy to set boundary conditions" PACKAGE core)
-add_example(explicit "Example on how to run an explicit simulation" PACKAGE core)
-add_example(io "Example on how to perform Input/Output operations" PACKAGE core)
-add_example(implicit "Example on how to run an implicit simulation" PACKAGE implicit)
-add_example(static "Example on how to run a static simulation" PACKAGE implicit)
-add_example(parallel "Example of how to write a parallel code with Akantu" PACKAGE parallel)
-add_example(cohesive_element "Cohesive element examples" PACKAGE cohesive_element)
-add_example(structural_mechanics "Structural mechanics model examples" PACKAGE structural_mechanics)
-add_example(heat_transfer "Example on how to run heat transfer simulation" PACKAGE heat_transfer)
-add_example(python "Example on how to use the python interface" PACKAGE python_interface)
-add_example(embedded "Example on how to run embedded model simulation" PACKAGE embedded)
-add_example(contact_mechanics "Example on how to run contact mechanics model simulation" PACKAGE contact_mechanics)
-add_example(phase_field "Example on how to run phase field model simulation" PACKAGE phase_field)
+add_example(c++ "C++ examples" PACKAGE core)
+add_example(python "Python example" PACKAGE python_interface)
package_add_files_to_package(
examples/README.rst
cmake/AkantuExampleMacros.cmake
)
-
-
diff --git a/examples/README.rst b/examples/README.rst
index e317e4b13..1865e91e4 100644
--- a/examples/README.rst
+++ b/examples/README.rst
@@ -1,59 +1,41 @@
-========
Examples
========
-This examples demonstrate some of the principal features of **Akantu**. Each
-sub-folder contain concentrate on one particular features.
-
-Common features
----------------
-
-*boundary_conditions*
- This shows how to impose boundary conditions by using the group of elements
- defining the boundaries. Boundaries are applied mainly by using functors, some
- are predefined in akantu asshown in the sub-example 'predefined_bc'. If this
- is not sufficient the user can define it's one functor, example
- 'user_defined_bc'
-
-*io*
- This examples show some advanced features of the dumpers, to dump extra
- fields than the default ones
-
-*parallel*
- This example shows how to initialize a parallel computation
-
-*python*
- This examples show some basic usage of the python interface
+This part of the documentation describes the examples that are found in the
+`examples <https://gitlab.com/akantu/akantu/-/tree/master/examples>`_ in the
+repository. Akantu's example are separated in 2 types, the C++ and the python
+ones, respectively in the 2 sub-folders ``c++/`` and ``python/``. The structure of
+this documentation follows the folder structure of the ``examples`` folder.
-Solid Mechanics
----------------
+The examples can be compiled by setting the option ``AKANTU_EXAMPLES`` in the
+cmake configuration. They can be executed from after compilation from the
+``examples`` folder in the build directory. Even though the python examples do not
+need to be compiled, some file may still be generated it is then easier to run
+them from the build directory. In order to set the different environment
+variables needed a script ``akantu_environment.sh`` can be found in the build
+directory.
-*explicit*
- This examples shows a dynamic wave propagation in a beam. It uses a central
- difference explicit time integration scheme.
+Examples in both 2D and 3D are presented with the dimension is specified in the
+respective example titles. The only distinctions between a 2D and a 3D simulation lie in
+the mesh declaration.
+In C++:
-*implicit*
- This example shows how to use the implicit dynamic solver.
+.. code-block:: c++
-*static*
- This example shows how to do a static computation
+ const Int spatial_dimension = 2; // or 3 for 3D
+ Mesh mesh(spatial_dimension);
+ mesh.read("example_mesh.msh");
-*cohesive_element*
- This examples show some usage of the cohesive element in explicit or implicit
- and with extrinsic or intrinsic elements
+In Python:
-*new_material*
- This example shows how to write a custom material outside of **Akantu** and
- how to use it
+.. code-block:: python
-Heat transfer
--------------
+ spatial_dimension = 2 # or 3 for 3D
+ mesh = aka.Mesh(spatial_dimension)
+ mesh.read("example_mesh.msh")
-*heat_transfer*
- This example shows how to use the HeatTransferModel
+where ``example_mesh.msh`` is either a 2D or a 3D mesh.
-Structural mechanics
---------------------
+.. include:: examples/c++/README.rst
-*structural_mechanics*
- This example shows how to use the StructuralMechanicsModel
+.. include:: examples/python/README.rst
diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt
new file mode 100644
index 000000000..b643bbad3
--- /dev/null
+++ b/examples/c++/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_example(contact_mechanics_model "Example on how to run contact mechanics model simulation" PACKAGE contact_mechanics)
+add_example(diffusion_model "Example on how to run heat transfer simulation" PACKAGE diffusion)
+add_example(embedded_model "Example on how to run embedded model simulation" PACKAGE embedded)
+add_example(phase_field_model "Example on how to run phase field model simulation" PACKAGE phase_field)
+add_example(solid_mechanics_cohesive_model "Cohesive element examples" PACKAGE cohesive_element)
+add_example(solid_mechanics_model "Solid mechanics examples" PACKAGE solid_mechanics)
+add_example(structural_mechanics_model "Structural mechanics model examples" PACKAGE structural_mechanics)
diff --git a/examples/c++/README.rst b/examples/c++/README.rst
new file mode 100644
index 000000000..2992c8227
--- /dev/null
+++ b/examples/c++/README.rst
@@ -0,0 +1,12 @@
+C++ Examples
+------------
+
+.. include:: examples/c++/solid_mechanics_model/README.rst
+
+.. include:: examples/c++/solid_mechanics_cohesive_model/README.rst
+
+.. include:: examples/c++/contact_mechanics_model/README.rst
+
+.. include:: examples/c++/diffusion_model/README.rst
+
+.. include:: examples/c++/phase_field_model/README.rst
diff --git a/examples/contact_mechanics/CMakeLists.txt b/examples/c++/contact_mechanics_model/CMakeLists.txt
similarity index 100%
rename from examples/contact_mechanics/CMakeLists.txt
rename to examples/c++/contact_mechanics_model/CMakeLists.txt
diff --git a/examples/c++/contact_mechanics_model/README.rst b/examples/c++/contact_mechanics_model/README.rst
new file mode 100644
index 000000000..29acf48cd
--- /dev/null
+++ b/examples/c++/contact_mechanics_model/README.rst
@@ -0,0 +1,44 @@
+Contact mechanics model (2D)
+````````````````````````````
+
+:Sources:
+
+ .. collapse:: contact_explicit_dynamic.cc (click to expand)
+
+ .. literalinclude:: examples/c++/contact_mechanics_model/contact_explicit_dynamic.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: contact_explicit_static.cc (click to expand)
+
+ .. literalinclude:: examples/c++/contact_mechanics_model/contact_explicit_static.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/contact_mechanics_model/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/`` `contact_mechanics_model <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/contact_mechanics_model>`_
+
+
+`contact_explicit_static` and `contact_explicit_dynamic` are solving a 2D Hertz contact patch test using the ``CouplerSolidContact``.
+The two examples follow what is described extensively in section :ref:`sect-cmm-coupling-with-smm`. The only main difference between `contact_explicit_static` and `contact_explicit_dynamic` is the solver used::
+
+ // for contact_explicit_static
+ coupler.initFull(_analysis_method = _static);
+ // for contact_explicit_dynamic
+ coupler.initFull(_analysis_method = _explicit_lumped_mass);
+
+The ``material.dat`` file contain a ``contact_detector`` and a ``contact_resolution penalty_linear`` section as explains in section :ref:`sect-cmm-contact-detection`.
+
+.. figure:: examples/c++/contact_mechanics_model/images/hertz.svg
+ :align: center
+ :width: 60%
+
+.. figure:: examples/c++/contact_mechanics_model/images/hertz.png
+ :align: center
+ :width: 60%
diff --git a/examples/contact_mechanics/cohesive-contact.geo b/examples/c++/contact_mechanics_model/cohesive-contact.geo
similarity index 100%
rename from examples/contact_mechanics/cohesive-contact.geo
rename to examples/c++/contact_mechanics_model/cohesive-contact.geo
diff --git a/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc b/examples/c++/contact_mechanics_model/cohesive_contact_explicit_dynamic.cc
similarity index 92%
rename from examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc
rename to examples/c++/contact_mechanics_model/cohesive_contact_explicit_dynamic.cc
index 6f0ba6b25..4a8eba8e9 100644
--- a/examples/contact_mechanics/cohesive_contact_explicit_dynamic.cc
+++ b/examples/c++/contact_mechanics_model/cohesive_contact_explicit_dynamic.cc
@@ -1,148 +1,143 @@
/**
* Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 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;
+ 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;
+ << "\n";
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;
+ << "," << epot + ekin << ","
+ << "\n";
}
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;
+ << "," << epot + ekin << ","
+ << "\n";
}
if (i % 1000 == 0) {
coupler.dump();
}
}
}
diff --git a/examples/contact_mechanics/contact_explicit_dynamic.cc b/examples/c++/contact_mechanics_model/contact_explicit_dynamic.cc
similarity index 91%
rename from examples/contact_mechanics/contact_explicit_dynamic.cc
rename to examples/c++/contact_mechanics_model/contact_explicit_dynamic.cc
index 03e7fb776..7a75947ae 100644
--- a/examples/contact_mechanics/contact_explicit_dynamic.cc
+++ b/examples/c++/contact_mechanics_model/contact_explicit_dynamic.cc
@@ -1,121 +1,115 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 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;
+ Real time_step{0.};
+ 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;
+ << "\n";
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;
+ << "," << epot + ekin << ","
+ << "\n";
}
if (i % 1000 == 0) {
coupler.dump();
}
}
- finalize();
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/contact_mechanics/contact_explicit_static.cc b/examples/c++/contact_mechanics_model/contact_explicit_static.cc
similarity index 94%
rename from examples/contact_mechanics/contact_explicit_static.cc
rename to examples/c++/contact_mechanics_model/contact_explicit_static.cc
index 6ebd407cc..be0b4b4a7 100644
--- a/examples/contact_mechanics/contact_explicit_static.cc
+++ b/examples/c++/contact_mechanics_model/contact_explicit_static.cc
@@ -1,84 +1,78 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 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;
+ 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;
+ return 0;
}
diff --git a/examples/contact_mechanics/hertz.geo b/examples/c++/contact_mechanics_model/hertz.geo
similarity index 100%
rename from examples/contact_mechanics/hertz.geo
rename to examples/c++/contact_mechanics_model/hertz.geo
diff --git a/examples/c++/contact_mechanics_model/images/hertz.png b/examples/c++/contact_mechanics_model/images/hertz.png
new file mode 100644
index 000000000..97d9963fe
Binary files /dev/null and b/examples/c++/contact_mechanics_model/images/hertz.png differ
diff --git a/examples/c++/contact_mechanics_model/images/hertz.svg b/examples/c++/contact_mechanics_model/images/hertz.svg
new file mode 100644
index 000000000..a4b76fc53
--- /dev/null
+++ b/examples/c++/contact_mechanics_model/images/hertz.svg
@@ -0,0 +1,921 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="1079pt"
+ height="1165pt"
+ viewBox="0 0 1079 1165"
+ version="1.1"
+ id="svg298"
+ sodipodi:docname="hertz.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+ <sodipodi:namedview
+ id="namedview300"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="pt"
+ showgrid="false"
+ inkscape:zoom="1.3454936"
+ inkscape:cx="491.26954"
+ inkscape:cy="334.07815"
+ inkscape:window-width="1537"
+ inkscape:window-height="1232"
+ inkscape:window-x="604"
+ inkscape:window-y="63"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg298" />
+ <title
+ id="title258">hertz</title>
+ <desc
+ id="desc260">
+Creator: GL2PS 1.4.2, (C) 1999-2020 C. Geuzaine
+For: Gmsh
+CreationDate: Fri Sep 15 10:20:30 2023
+</desc>
+ <defs
+ id="defs262" />
+ <g
+ id="g296">
+ <circle
+ fill="#5a5a5a"
+ cx="154.143"
+ cy="630.669"
+ r="2"
+ id="circle264" />
+ <circle
+ fill="#5a5a5a"
+ cx="539.5"
+ cy="245.312"
+ r="2"
+ id="circle266" />
+ <circle
+ fill="#5a5a5a"
+ cx="924.857"
+ cy="630.669"
+ r="2"
+ id="circle268" />
+ <circle
+ fill="#5a5a5a"
+ cx="154.143"
+ cy="630.669"
+ r="2"
+ id="circle270" />
+ <circle
+ fill="#5a5a5a"
+ cx="154.143"
+ cy="919.688"
+ r="2"
+ id="circle272" />
+ <circle
+ fill="#5a5a5a"
+ cx="924.857"
+ cy="919.688"
+ r="2"
+ id="circle274" />
+ <circle
+ fill="#5a5a5a"
+ cx="154.143"
+ cy="245.312"
+ r="2"
+ id="circle276" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="154.143,630.669 161.709,630.595 169.272,630.373 176.829,630.001 184.377,629.482 191.915,628.814 199.437,627.999 206.941,627.036 214.426,625.925 221.887,624.668 229.322,623.265 236.729,621.716 244.103,620.022 251.442,618.184 258.744,616.202 266.006,614.076 273.225,611.809 280.397,609.4 287.521,606.851 294.594,604.163 301.613,601.336 308.574,598.372 315.477,595.272 322.316,592.037 329.091,588.668 335.799,585.167 342.437,581.535 349.001,577.773 355.491,573.883 361.904,569.867 368.236,565.725 374.485,561.46 380.65,557.073 386.728,552.566 392.715,547.94 398.611,543.198 404.412,538.34 410.117,533.37 415.724,528.289 421.229,523.099 426.631,517.801 431.929,512.398 437.119,506.893 442.201,501.287 447.171,495.582 452.028,489.78 456.771,483.885 461.396,477.897 465.903,471.82 470.291,465.655 474.556,459.405 478.697,453.073 482.714,446.661 486.604,440.171 490.365,433.606 493.998,426.969 497.499,420.261 500.867,413.486 504.102,406.646 507.203,399.744 510.167,392.782 512.993,385.764 515.682,378.691 518.23,371.567 520.639,364.395 522.907,357.176 525.032,349.914 527.014,342.612 528.853,335.272 530.546,327.898 532.095,320.492 533.499,313.057 534.755,305.596 535.866,298.111 536.829,290.606 537.645,283.084 538.312,275.547 538.832,267.999 539.203,260.441 539.426,252.878 539.5,245.312 154.143,245.312"
+ id="polyline278" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="154.143,919.688 924.857,919.688 924.857,630.669 154.143,630.669 154.143,919.688"
+ id="polyline280" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="154.143,245.312 154.143,630.669"
+ id="polyline282" />
+ <text
+ fill="#000000"
+ x="1052"
+ y="1122"
+ font-size="15"
+ text-anchor="start"
+ dy="0"
+ font-family="Helvetica"
+ id="text284">X</text>
+ <text
+ fill="#000000"
+ x="1022"
+ y="1092"
+ font-size="15"
+ text-anchor="start"
+ dy="0"
+ font-family="Helvetica"
+ id="text286">Y</text>
+ <text
+ fill="#000000"
+ x="1022"
+ y="1122"
+ font-size="15"
+ text-anchor="start"
+ dy="0"
+ font-family="Helvetica"
+ id="text288">Z</text>
+ <polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1019,1125 1049,1125"
+ id="polyline290" />
+ <polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1019,1125 1019,1095"
+ id="polyline292" />
+ <polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1019,1125 1019,1125"
+ id="polyline294" />
+ </g>
+ <g
+ id="g4256"
+ transform="translate(0.56264634,-1.5)">
+ <g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" />
+ </g>
+ </g>
+ <g
+ id="g4690"
+ transform="translate(-49.201791,-151.60159)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-2"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="rotate(-90,690.61551,552.95676)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-6"
+ cx="-1070.6442"
+ cy="201.78468"
+ r="3.0005257"
+ transform="rotate(-90)" />
+ <g
+ id="g4241-5"
+ transform="rotate(-90,573.10992,625.54104)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-94" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-90" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-91" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-711" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-5" />
+ </g>
+ </g>
+ <g
+ id="g4256-3"
+ transform="translate(0.56264634,166.93832)">
+ <g
+ id="g2882-6"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-1"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-29"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-19"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-4"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-7"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6" />
+ </g>
+ </g>
+ <g
+ id="g4256-1"
+ transform="translate(0.56264634,335.37664)">
+ <g
+ id="g2882-06"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-20"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-61"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-55"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-47"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-6"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-4" />
+ </g>
+ </g>
+ <g
+ id="g4256-5"
+ transform="translate(0.56264634,503.81497)">
+ <g
+ id="g2882-25"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-4"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-74"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-4"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-30"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-7"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-8"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-31" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-49" />
+ </g>
+ </g>
+ <g
+ id="g4256-2"
+ transform="translate(0.56264634,672.25329)">
+ <g
+ id="g2882-0"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-9"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-64"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-48" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-71" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-7" />
+ </g>
+ </g>
+ <g
+ id="g4690-9"
+ transform="translate(722.83012,-151.60159)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-2-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="rotate(-90,690.61551,552.95676)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-6-7"
+ cx="-1070.6442"
+ cy="201.78468"
+ r="3.0005257"
+ transform="rotate(-90)" />
+ <g
+ id="g4241-5-6"
+ transform="rotate(-90,573.10992,625.54104)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-94-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-90-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-91-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-7-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-711-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-5-3" />
+ </g>
+ </g>
+ <g
+ id="g4690-94"
+ transform="translate(143.80619,-151.60159)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-2-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="rotate(-90,690.61551,552.95676)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-6-1"
+ cx="-1070.6442"
+ cy="201.78468"
+ r="3.0005257"
+ transform="rotate(-90)" />
+ <g
+ id="g4241-5-2"
+ transform="rotate(-90,573.10992,625.54104)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-94-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-90-39" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-91-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-7-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-711-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-5-5" />
+ </g>
+ </g>
+ <g
+ id="g4690-0"
+ transform="translate(336.81416,-151.60159)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-2-9"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="rotate(-90,690.61551,552.95676)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-6-6"
+ cx="-1070.6442"
+ cy="201.78468"
+ r="3.0005257"
+ transform="rotate(-90)" />
+ <g
+ id="g4241-5-3"
+ transform="rotate(-90,573.10992,625.54104)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-94-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-90-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-91-61" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-7-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-711-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-5-9" />
+ </g>
+ </g>
+ <g
+ id="g4690-8"
+ transform="translate(529.82214,-151.60159)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-2-4"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="rotate(-90,690.61551,552.95676)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-6-8"
+ cx="-1070.6442"
+ cy="201.78468"
+ r="3.0005257"
+ transform="rotate(-90)" />
+ <g
+ id="g4241-5-1"
+ transform="rotate(-90,573.10992,625.54104)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-94-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-90-30" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-91-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-7-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-711-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-5-4" />
+ </g>
+ </g>
+ <g
+ id="g4964"
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(-33.444964,48.386599)">
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,196.89933 h 4.86931"
+ id="path4930" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,180.21224 h 4.86931"
+ id="path4930-7" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 187.70032,196.80822 V 180.30335"
+ id="path4932" />
+ </g>
+ <g
+ id="g4964-5"
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(43.567877,48.386599)">
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,196.89933 h 4.86931"
+ id="path4930-9" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,180.21224 h 4.86931"
+ id="path4930-7-6" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 187.70032,196.80822 V 180.30335"
+ id="path4932-2" />
+ </g>
+ <g
+ id="g4964-1"
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(197.59356,48.386599)">
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,196.89933 h 4.86931"
+ id="path4930-78" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,180.21224 h 4.86931"
+ id="path4930-7-5" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 187.70032,196.80822 V 180.30335"
+ id="path4932-74" />
+ </g>
+ <g
+ id="g4964-18"
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(274.6064,48.386599)">
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,196.89933 h 4.86931"
+ id="path4930-5" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,180.21224 h 4.86931"
+ id="path4930-7-9" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 187.70032,196.80822 V 180.30335"
+ id="path4932-75" />
+ </g>
+ <g
+ id="g4964-3"
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(351.61924,48.386599)">
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,196.89933 h 4.86931"
+ id="path4930-8" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,180.21224 h 4.86931"
+ id="path4930-7-8" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 187.70032,196.80822 V 180.30335"
+ id="path4932-3" />
+ </g>
+ <g
+ id="g4964-189"
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(120.58072,48.386599)">
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,196.89933 h 4.86931"
+ id="path4930-6" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 185.26567,180.21224 h 4.86931"
+ id="path4930-7-4" />
+ <path
+ style="fill:#ed1423;fill-opacity:1;stroke:#d81414;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 187.70032,196.80822 V 180.30335"
+ id="path4932-33" />
+ </g>
+</svg>
diff --git a/examples/contact_mechanics/material-cohesive.dat b/examples/c++/contact_mechanics_model/material-cohesive.dat
similarity index 100%
rename from examples/contact_mechanics/material-cohesive.dat
rename to examples/c++/contact_mechanics_model/material-cohesive.dat
diff --git a/examples/contact_mechanics/material.dat b/examples/c++/contact_mechanics_model/material.dat
similarity index 100%
rename from examples/contact_mechanics/material.dat
rename to examples/c++/contact_mechanics_model/material.dat
diff --git a/examples/heat_transfer/CMakeLists.txt b/examples/c++/diffusion_model/CMakeLists.txt
similarity index 71%
rename from examples/heat_transfer/CMakeLists.txt
rename to examples/c++/diffusion_model/CMakeLists.txt
index 5b7af083d..5cd70d071 100644
--- a/examples/heat_transfer/CMakeLists.txt
+++ b/examples/c++/diffusion_model/CMakeLists.txt
@@ -1,43 +1,41 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(heat_diffusion_mesh_2d square.geo 2 2)
+add_mesh(heat_diffusion_mesh_3d cube.geo 3 2)
-add_mesh(heat_transfer_mesh_2d square.geo 2 2)
-add_mesh(heat_transfer_mesh_3d cube.geo 3 2)
-
-register_example(heat_transfer_dynamics_2d
- SOURCES heat_transfer_dynamics_2d.cc
- DEPENDS heat_transfer_mesh_2d
+register_example(heat_diffusion_dynamics_2d
+ SOURCES heat_diffusion_dynamics_2d.cc
+ DEPENDS heat_diffusion_mesh_2d
FILES_TO_COPY material.dat
)
-register_example(heat_transfer_static_2d
- SOURCES heat_transfer_static_2d.cc
- DEPENDS heat_transfer_mesh_2d
+register_example(heat_diffusion_static_2d
+ SOURCES heat_diffusion_static_2d.cc
+ DEPENDS heat_diffusion_mesh_2d
FILES_TO_COPY material.dat
)
-register_example(heat_transfer_dynamics_3d
- SOURCES heat_transfer_dynamics_3d.cc
- DEPENDS heat_transfer_mesh_3d
+register_example(heat_diffusion_dynamics_3d
+ SOURCES heat_diffusion_dynamics_3d.cc
+ DEPENDS heat_diffusion_mesh_3d
FILES_TO_COPY material.dat
)
-
diff --git a/examples/c++/diffusion_model/README.rst b/examples/c++/diffusion_model/README.rst
new file mode 100644
index 000000000..f7d3c5bfd
--- /dev/null
+++ b/examples/c++/diffusion_model/README.rst
@@ -0,0 +1,101 @@
+Diffusion Model (2D and 3D)
+```````````````````````````
+
+:Sources:
+
+ .. collapse:: heat_diffusion_static_2d.cc (click to expand)
+
+ .. literalinclude:: examples/c++/diffusion_model/heat_diffusion_static_2d.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/diffusion_model/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/`` `diffusion_model <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/diffusion_model>`_
+
+
+In ``diffusion_model``, examples of the ``HeatTransferModel`` are presented.
+
+An example of a static heat propagation is presented in
+``heat_diffusion_static_2d.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 non centered hot point maintained at
+:math:`300 \text{K}`. :numref:`fig-ex-diffusion_static` presents the geometry
+of this case (left) and the results (right). 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 simulation is set following the procedure described in :ref:`sect-dm-using`
+
+.. _fig-ex-diffusion_static:
+.. figure:: examples/c++/diffusion_model/images/diffusion_static.png
+ :align: center
+ :width: 70%
+
+ Initial (left) and final (right) temperature field
+
+
+:Sources:
+
+ .. collapse:: heat_diffusion_dynamic_2d.cc (click to expand)
+
+ .. literalinclude:: examples/c++/diffusion_model/heat_diffusion_static_2d.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/diffusion_model/material.dat
+ :language: text
+
+In ``heat_diffusion_dynamics_2d.cc``, the same example is solved dynamically
+using an explicit time scheme. The time step used is :math:`0.12 \text{s}`. The only main difference with the previous example lies in the model initiation::
+
+ model.initFull(_analysis_method = _explicit_lumped_mass);
+
+.. _fig-ex-diffusion_explicit:
+.. figure:: examples/c++/diffusion_model/images/hot-point-2.png
+ :align: center
+ :width: 60%
+
+ Temperature field after 15000 time steps = 30 minutes. The lines represent
+ iso-surfaces.
+
+:Sources:
+
+ .. collapse:: heat_diffusion_dynamic_2d.cc (click to expand)
+
+ .. literalinclude:: examples/c++/diffusion_model/heat_diffusion_static_2d.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/diffusion_model/material.dat
+ :language: text
+
+In ``heat_diffusion_dynamics_3d.cc``, a 3D explicit dynamic heat propagation
+problem is solved. It consists of a cube having an initial temperature of
+:math:`100 \text{K}` everywhere but a centered sphere maintained at
+:math:`300 \text{K}`.
+The simulation is set exactly as ``heat_diffusion_dynamics_2d.cc`` except that the mesh is now a 3D mesh and that the heat source has a third coordinate and is placed at the cube center.
+The mesh is initialized with::
+
+ Int spatial_dimension = 3;
+ Mesh mesh(spatial_dimension);
+ mesh.read("cube.msh");
+
+:numref:`fig-ex-diffusion_3d` presents the resulting temperature field evolution.
+
+.. _fig-ex-diffusion_3d:
+.. figure:: examples/c++/diffusion_model/images/diffusion_3d.gif
+ :align: center
+ :width: 70%
+
+ Temperature field evolution.
diff --git a/examples/heat_transfer/cube.geo b/examples/c++/diffusion_model/cube.geo
similarity index 100%
rename from examples/heat_transfer/cube.geo
rename to examples/c++/diffusion_model/cube.geo
diff --git a/examples/heat_transfer/cube_tet.geo b/examples/c++/diffusion_model/cube_tet.geo
similarity index 100%
rename from examples/heat_transfer/cube_tet.geo
rename to examples/c++/diffusion_model/cube_tet.geo
diff --git a/examples/heat_transfer/heat_transfer_dynamics_2d.cc b/examples/c++/diffusion_model/heat_diffusion_dynamics_2d.cc
similarity index 87%
rename from examples/heat_transfer/heat_transfer_dynamics_2d.cc
rename to examples/c++/diffusion_model/heat_diffusion_dynamics_2d.cc
index 3f6cd9ad4..3cf8177d0 100644
--- a/examples/heat_transfer/heat_transfer_dynamics_2d.cc
+++ b/examples/c++/diffusion_model/heat_diffusion_dynamics_2d.cc
@@ -1,92 +1,97 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 Int 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();
+ model.initFull(_analysis_method = _explicit_lumped_mass);
// get stable time step
Real time_step = model.getStableTimeStep() * 0.8;
- std::cout << "time step is:" << time_step << std::endl;
+ std::cout << "time step is:" << time_step << "\n";
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.;
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)
+ if (spatial_dimension > 1) {
dy = nodes(i, 1) - length / 4.;
- if (spatial_dimension == 3)
+ }
+ 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.setBaseName("heat_diffusion_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)
+ if (i % 100 == 0) {
model.dump();
- if (i % 10 == 0)
- std::cout << "Step " << i << "/" << max_steps << std::endl;
+ }
+ if (i % 10 == 0) {
+ std::cout << "Step " << i << "/" << max_steps << "\n";
+ }
}
std::cout << "\n\n Stable Time Step is : " << time_step << "\n \n"
- << std::endl;
+ << "\n";
return 0;
}
diff --git a/examples/heat_transfer/heat_transfer_dynamics_3d.cc b/examples/c++/diffusion_model/heat_diffusion_dynamics_3d.cc
similarity index 83%
rename from examples/heat_transfer/heat_transfer_dynamics_3d.cc
rename to examples/c++/diffusion_model/heat_diffusion_dynamics_3d.cc
index 155eda419..aa6dfe5f1 100644
--- a/examples/heat_transfer/heat_transfer_dynamics_3d.cc
+++ b/examples/c++/diffusion_model/heat_diffusion_dynamics_3d.cc
@@ -1,98 +1,92 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
-
+/* -------------------------------------------------------------------------- */
+#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
-
-Int spatial_dimension = 3;
-ElementType type = _tetrahedron_4;
-
/* -------------------------------------------------------------------------- */
+const Int spatial_dimension = 3;
+
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();
+ model.initFull(_analysis_method = _explicit_lumped_mass);
// 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;
+ std::cout << "Stable Time Step is : " << time_step / .8 << "\n";
+ std::cout << "time step is:" << time_step << "\n";
model.setTimeStep(time_step);
/// boundary conditions
const Array<Real> & nodes = mesh.getNodes();
Array<bool> & boundary = model.getBlockedDOFs();
Array<Real> & temperature = model.getTemperature();
auto nb_nodes = mesh.getNbNodes();
- double length;
- length = 1.;
+ double length = 1.;
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.setBaseName("heat_diffusion_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)
+ if (i % 100 == 0) {
model.dump();
+ }
if (i % 10 == 0) {
- std::cout << "Step " << i << "/" << max_steps << std::endl;
+ std::cout << "Step " << i << "/" << max_steps << "\n";
}
}
return 0;
}
diff --git a/examples/heat_transfer/heat_transfer_static_2d.cc b/examples/c++/diffusion_model/heat_diffusion_static_2d.cc
similarity index 91%
rename from examples/heat_transfer/heat_transfer_static_2d.cc
rename to examples/c++/diffusion_model/heat_diffusion_static_2d.cc
index edf161db6..e2f173e95 100644
--- a/examples/heat_transfer/heat_transfer_static_2d.cc
+++ b/examples/c++/diffusion_model/heat_diffusion_static_2d.cc
@@ -1,84 +1,81 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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;
-
/* -------------------------------------------------------------------------- */
-Int spatial_dimension = 2;
-std::string base_name;
+
+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(_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.;
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.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)
+ 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)
+ }
+ if (std::abs(dx - length) < 1e-4 || std::abs(dy - length) < 1e-4) {
blocked_dofs(i) = true;
+ }
}
- model.setBaseName("heat_transfer_static_2d");
+ model.setBaseName("heat_diffusion_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/c++/diffusion_model/images/diffusion_3d.gif b/examples/c++/diffusion_model/images/diffusion_3d.gif
new file mode 100644
index 000000000..858731005
Binary files /dev/null and b/examples/c++/diffusion_model/images/diffusion_3d.gif differ
diff --git a/examples/c++/diffusion_model/images/diffusion_static.png b/examples/c++/diffusion_model/images/diffusion_static.png
new file mode 100644
index 000000000..2d5c35ef5
Binary files /dev/null and b/examples/c++/diffusion_model/images/diffusion_static.png differ
diff --git a/examples/c++/diffusion_model/images/hot-point-1.png b/examples/c++/diffusion_model/images/hot-point-1.png
new file mode 100644
index 000000000..6349ba329
Binary files /dev/null and b/examples/c++/diffusion_model/images/hot-point-1.png differ
diff --git a/examples/c++/diffusion_model/images/hot-point-2.png b/examples/c++/diffusion_model/images/hot-point-2.png
new file mode 100644
index 000000000..2325ee893
Binary files /dev/null and b/examples/c++/diffusion_model/images/hot-point-2.png differ
diff --git a/examples/c++/diffusion_model/material.dat b/examples/c++/diffusion_model/material.dat
new file mode 100644
index 000000000..251f80d25
--- /dev/null
+++ b/examples/c++/diffusion_model/material.dat
@@ -0,0 +1,13 @@
+model heat_transfer_model [
+ constitutive_law heat_diffusion [
+ name = test
+ density = 8940
+ capacity = 385
+ conductivity = [[401, 0, 0], \
+ [0, 401, 0], \
+ [0, 0, 401]]
+ ]
+]
+
+
+
diff --git a/examples/heat_transfer/square.geo b/examples/c++/diffusion_model/square.geo
similarity index 100%
rename from examples/heat_transfer/square.geo
rename to examples/c++/diffusion_model/square.geo
diff --git a/examples/embedded/CMakeLists.txt b/examples/c++/embedded_model/CMakeLists.txt
similarity index 100%
rename from examples/embedded/CMakeLists.txt
rename to examples/c++/embedded_model/CMakeLists.txt
diff --git a/examples/embedded/concrete.geo b/examples/c++/embedded_model/concrete.geo
similarity index 100%
rename from examples/embedded/concrete.geo
rename to examples/c++/embedded_model/concrete.geo
diff --git a/examples/embedded/embedded.cc b/examples/c++/embedded_model/embedded.cc
similarity index 100%
rename from examples/embedded/embedded.cc
rename to examples/c++/embedded_model/embedded.cc
diff --git a/examples/embedded/material.dat b/examples/c++/embedded_model/material.dat
similarity index 100%
rename from examples/embedded/material.dat
rename to examples/c++/embedded_model/material.dat
diff --git a/examples/embedded/reinforcement.geo b/examples/c++/embedded_model/reinforcement.geo
similarity index 100%
rename from examples/embedded/reinforcement.geo
rename to examples/c++/embedded_model/reinforcement.geo
diff --git a/examples/phase_field/CMakeLists.txt b/examples/c++/phase_field_model/CMakeLists.txt
similarity index 100%
rename from examples/phase_field/CMakeLists.txt
rename to examples/c++/phase_field_model/CMakeLists.txt
diff --git a/examples/c++/phase_field_model/README.rst b/examples/c++/phase_field_model/README.rst
new file mode 100644
index 000000000..52975652d
--- /dev/null
+++ b/examples/c++/phase_field_model/README.rst
@@ -0,0 +1,39 @@
+Phase-field model (2D) [Unstable]
+`````````````````````````````````
+
+static
+''''''
+
+:Sources:
+
+ .. collapse:: phase_field_notch.cc (click to expand)
+
+ .. literalinclude:: examples/c++/phase_field_model/phase_field_notch.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material_notch.dat (click to expand)
+
+ .. literalinclude:: examples/c++/phase_field_model/material_notch.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/`` `phase_field_model <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/phase_field_model>`_
+
+
+`phase_field_notch.cc` shows hot to set a quasi-static fracture simulation with phase-field. The geometry of the solid is a square plate with a notch. The loading is an imposed displacement at the top of the plate (mode I).
+
+.. figure:: examples/python/phase_field_model/images/phasefield-static-geo.svg
+ :align: center
+ :width: 50%
+
+ Notched plate with boundary conditions and imposed displacement.
+
+In addition, this example shows how to extract clusters delimited by the mesh boundaries and elements with damage values beyond a threshold. This can be useful to extract fragments after crack propagation.
+
+.. figure:: examples/c++/phase_field_model/images/phase_field_clusters.png
+ :align: center
+ :width: 90%
+
+ Damage field after a few iterations and two clusters (fragments) extracted.
diff --git a/examples/c++/phase_field_model/images/phase_field_clusters.png b/examples/c++/phase_field_model/images/phase_field_clusters.png
new file mode 100644
index 000000000..fd94956f3
Binary files /dev/null and b/examples/c++/phase_field_model/images/phase_field_clusters.png differ
diff --git a/examples/phase_field/material_notch.dat b/examples/c++/phase_field_model/material_notch.dat
similarity index 100%
rename from examples/phase_field/material_notch.dat
rename to examples/c++/phase_field_model/material_notch.dat
diff --git a/examples/phase_field/phase_field_notch.cc b/examples/c++/phase_field_model/phase_field_notch.cc
similarity index 72%
rename from examples/phase_field/phase_field_notch.cc
rename to examples/c++/phase_field_model/phase_field_notch.cc
index 18371775a..d787163c2 100644
--- a/examples/phase_field/phase_field_notch.cc
+++ b/examples/c++/phase_field_model/phase_field_notch.cc
@@ -1,126 +1,124 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "group_manager.hh"
-#include "non_linear_solver.hh"
#include "phase_field_element_filter.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 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");
+ // The model coupler contains the solid mechanics and the phase-field models
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
+ // Each model can bet set separately
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);
+ // Dirichlet BC
model.applyBC(BC::Dirichlet::FixedValue(0., _y), "bottom");
model.applyBC(BC::Dirichlet::FixedValue(0., _x), "left");
+ // Dumper settings
model.setBaseName("phase_notch");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
- Int nbSteps = 1000;
+ const Int nb_steps = 1000;
Real increment = 6e-6;
Int nb_staggered_steps = 5;
auto start_time = clk::now();
- for (Int s = 1; s < nbSteps; ++s) {
-
+ // Main loop over the loading steps
+ for (Int s = 1; s < nb_steps; ++s) {
if (s >= 500) {
increment = 2e-6;
nb_staggered_steps = 10;
}
if (s % 200 == 0) {
- constexpr char wheel[] = "/-\\|";
+ constexpr std::array<char, 5> 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
+ int idx = (s / 10) % 4;
+ std::cout << "\r[" << wheel.at(idx) << "] " << std::setw(5) << s << "/"
+ << nb_steps << " (" << 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)"
+ << second((nb_steps - s) * time_per_step).count() << "s)"
<< std::string(' ', 20) << std::flush;
}
model.applyBC(BC::Dirichlet::IncrementValue(increment, _y), "top");
+ /* At each step, the two solvers are called alternately. Here a fixed number
+ * of staggered iterations is set for simplicity but a convergence based on
+ * the displacements, damage and/or energy can also be used to exit the
+ * internal loop.*/
for (Idx i = 0; i < nb_staggered_steps; ++i) {
coupler.solve();
}
if (s % 100 == 0) {
model.dump();
}
}
+ /* Here a damage threshold is set and a mesh clustering function is called
+ * using the phase-field element filter. This allows to cluster the mesh into
+ * groups of elements separated by the mesh boundaries and "broken" elements
+ * with damage above the threshold. */
Real damage_limit = 0.15;
auto global_nb_clusters = mesh.createClusters(
spatial_dimension, "crack", PhaseFieldElementFilter(phase, damage_limit));
- auto nb_fragment = mesh.getNbElementGroups(spatial_dimension);
-
model.dumpGroup("crack_0");
+ model.dumpGroup("crack_1");
std::cout << std::endl;
std::cout << "Nb clusters: " << global_nb_clusters << std::endl;
- std::cout << "Nb fragments: " << nb_fragment << std::endl;
finalize();
return EXIT_SUCCESS;
}
diff --git a/examples/phase_field/phase_field_parallel.cc b/examples/c++/phase_field_model/phase_field_parallel.cc
similarity index 95%
rename from examples/phase_field/phase_field_parallel.cc
rename to examples/c++/phase_field_model/phase_field_parallel.cc
index 0d8278f55..8f419db65 100644
--- a/examples/phase_field/phase_field_parallel.cc
+++ b/examples/c++/phase_field_model/phase_field_parallel.cc
@@ -1,135 +1,129 @@
/**
* @file phase_field_parallel.cc
*
* @author Mohit Pundir <mohit.pundir@ethz.ch>
*
* @date creation: Mon May 09 2022
* @date last modification: Mon May 09 2022
*
* @brief Example of phase field model in parallel
*
*
* @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 "coupler_solid_phasefield.hh"
-#include "group_manager.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;
int main(int argc, char * argv[]) {
initialize("material_notch.dat", argc, argv);
// create mesh
Mesh mesh(spatial_dimension);
const auto & comm = Communicator::getStaticCommunicator();
Int prank = comm.whoAmI();
if (prank == 0) {
// Read the mesh
mesh.read("square_notch.msh");
}
mesh.distribute();
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_parallel");
model.addDumpField("stress");
model.addDumpField("grad_u");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
if (mesh.isDistributed()) {
// phase.addDumpField("partitions");
}
phase.dump();
UInt nbSteps = 1000;
Real increment = 6e-6;
UInt nb_staggered_steps = 5;
auto start_time = clk::now();
for (UInt s = 1; s < nbSteps; ++s) {
if (s >= 500) {
increment = 2e-6;
nb_staggered_steps = 10;
}
if (s % 10 == 0 && prank == 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");
for (UInt i = 0; i < nb_staggered_steps; ++i) {
coupler.solve();
}
if (s % 100 == 0) {
model.dump();
}
}
- finalize();
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/phase_field/square_notch.geo b/examples/c++/phase_field_model/square_notch.geo
similarity index 100%
rename from examples/phase_field/square_notch.geo
rename to examples/c++/phase_field_model/square_notch.geo
diff --git a/examples/cohesive_element/CMakeLists.txt b/examples/c++/solid_mechanics_cohesive_model/CMakeLists.txt
similarity index 100%
rename from examples/cohesive_element/CMakeLists.txt
rename to examples/c++/solid_mechanics_cohesive_model/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_cohesive_model/README.rst b/examples/c++/solid_mechanics_cohesive_model/README.rst
new file mode 100644
index 000000000..a54bdddef
--- /dev/null
+++ b/examples/c++/solid_mechanics_cohesive_model/README.rst
@@ -0,0 +1,13 @@
+Solid Mechanics Cohesive Model
+``````````````````````````````
+Solid mechanics cohesive model examples are shown in ``solid_mechanics_cohesive_model``. This new model is called in a very similar way as the solid mechanics model::
+
+ SolidMechanicsModelCohesive model(mesh);
+
+Cohesive elements can be inserted intrinsically (when the mesh is generated) or extrinsically (during the simulation).
+
+.. include:: examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/README.rst
+
+.. include:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/README.rst
+
+.. include:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/README.rst
diff --git a/examples/cohesive_element/cohesive_extrinsic/CMakeLists.txt b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/CMakeLists.txt
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic/CMakeLists.txt
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/README.rst b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/README.rst
new file mode 100644
index 000000000..c53985370
--- /dev/null
+++ b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/README.rst
@@ -0,0 +1,45 @@
+cohesive_extrinsic (2D)
+'''''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: cohesive_extrinsic.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/cohesive_extrinsic.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_cohesive_model/`` `cohesive_extrinsic <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/>`_
+
+
+In ``cohesive_extrinsic``, an example of extrinsic cohesive elements is shown.
+An extrinsic simulation is initialized by setting ``_is_extrinsic`` argument of ``model.initFull`` to ``true``::
+
+ model.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = true);
+
+Cohesive elements are inserted during the simulation but at a location restricted with::
+
+ CohesiveElementInserter & inserter = model.getElementInserter();
+ inserter.setLimit(_y, 0.30, 0.20);
+ model.updateAutomaticInsertion();
+
+During the simulation, stress has to be checked in order to insert cohesive elements where the stress criterion is reached. This check is performed by calling the method ``checkCohesiveStress`` before each step resolution::
+
+ model.checkCohesiveStress();
+ model.solveStep();
+
+For this specific example, a displacement is imposed based on the elements location. The corresponding displacements is shown in :numref:`fig-ex-cohesive-ext`.
+
+.. _fig-ex-cohesive-ext:
+.. figure:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/images/cohesive_extrinsic.gif
+ :align: center
+ :width: 90%
+
+ Displacement in the y direction for the cohesive_extrinsic example.
diff --git a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/cohesive_extrinsic.cc
similarity index 74%
rename from examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/cohesive_extrinsic.cc
index 5c455e103..28b092864 100644
--- a/examples/cohesive_element/cohesive_extrinsic/cohesive_extrinsic.cc
+++ b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/cohesive_extrinsic.cc
@@ -1,118 +1,121 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 Int spatial_dimension = 2;
+ const Int dim = 2;
const Int max_steps = 1000;
- Mesh mesh(spatial_dimension);
+ Mesh mesh(dim);
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;
+ std::cout << "Time step: " << time_step << "\n";
+ // updated the insertion limits
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();
Int nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (Int n = 0; n < nb_nodes; ++n) {
- if (position(n, 1) > 0.99 || position(n, 1) < -0.99) {
- boundary(n, 1) = true;
+ for (auto && [pos, boun] :
+ zip(make_view(position, dim), make_view(boundary, dim))) {
+ if (pos(_y) > 0.99 or pos(_y) < -0.99) {
+ boun(_y) = true;
}
-
- if (position(n, 0) > 0.99 || position(n, 0) < -0.99) {
- boundary(n, 0) = true;
+ if (pos(_x) > 0.99 or pos(_x) < -0.99) {
+ boun(_x) = 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 (Int n = 0; n < nb_nodes; ++n) {
- velocity(n, 1) = loading_rate * position(n, 1);
+ for (auto && [pos, vel] :
+ zip(make_view(position, dim), make_view(velocity, dim))) {
+ vel(_y) = loading_rate * pos(_y);
}
/// Main loop
for (Int s = 1; s <= max_steps; ++s) {
/// update displacement on extreme nodes
- 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);
+ for (auto && [pos, disp] :
+ zip(make_view(position, dim), make_view(displacement, dim))) {
+ if (pos(_y) > 0.99 or pos(_y) < -0.99) {
+ disp(_y) += disp_update * pos(_y);
}
}
+ // check wether cohesive elements should be inserted
model.checkCohesiveStress();
model.solveStep();
if (s % 10 == 0) {
model.dump();
- std::cout << "passing step " << s << "/" << max_steps << std::endl;
+ std::cout << "passing step " << s << "/" << max_steps << "\n";
}
}
Real Ed = model.getEnergy("dissipated");
Real Edt = 200 * std::sqrt(2);
- std::cout << Ed << " " << Edt << std::endl;
+ std::cout << Ed << " " << Edt << "\n";
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
- std::cout << "The dissipated energy is incorrect" << std::endl;
- return EXIT_FAILURE;
+ std::cout << "The dissipated energy is incorrect"
+ << "\n";
+ return -1;
}
- finalize();
-
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/images/cohesive_extrinsic.gif b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/images/cohesive_extrinsic.gif
new file mode 100644
index 000000000..2d75fd400
Binary files /dev/null and b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/images/cohesive_extrinsic.gif differ
diff --git a/examples/cohesive_element/cohesive_extrinsic/material.dat b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/material.dat
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic/material.dat
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/material.dat
diff --git a/examples/cohesive_element/cohesive_extrinsic/triangle.geo b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/triangle.geo
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic/triangle.geo
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/triangle.geo
diff --git a/examples/cohesive_element/cohesive_extrinsic/triangle.msh b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/triangle.msh
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic/triangle.msh
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic/triangle.msh
diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/CMakeLists.txt b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/CMakeLists.txt
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic_ig_tg/CMakeLists.txt
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/README.rst b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/README.rst
new file mode 100644
index 000000000..93c662614
--- /dev/null
+++ b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/README.rst
@@ -0,0 +1,39 @@
+cohesive_extrinsic_ig_tg (2D)
+'''''''''''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: cohesive_extrinsic_ig_tg.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. _mat-cohesive-extrinsic-ig-tg:
+ .. literalinclude:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/material.dat
+ :language: text
+ :caption:
+
+:Location:
+
+ ``examples/c++/solid_mechanics_cohesive_model/`` `cohesive_extrinsic_ig_tg <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/>`_
+
+
+In ``cohesive_extrinsic_ig_tg``, the insertion of cohesive element is not
+limited to a given location. Rather, elements at the boundaries of the block and
+those on the inside have a different critical stress ``sigma_c``. This is done
+by defining two different materials in the :ref:`mat-cohesive-extrinsic-ig-tg`.
+In this case the cohesive materials are chosen based on the bulk element on both
+side. This is achieved by defining ``MaterialCohesiveRules``
+
+The four block sides are then moved outwards. The resulting displacement is
+shown in :numref:`fig-ex-cohesive-ext-ig-tg`.
+
+.. _fig-ex-cohesive-ext-ig-tg:
+.. figure:: examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/images/cohesive_extrinsic_ig_tg.gif
+ :align: center
+ :width: 60%
+
+ Displacement magnitude for the cohesive_extrinsic_ig_tg example.
diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
similarity index 93%
rename from examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
index 3808c9b4b..d49b2df64 100644
--- a/examples/cohesive_element/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
+++ b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/cohesive_extrinsic_ig_tg.cc
@@ -1,141 +1,141 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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()(Idx node, VectorProxy<bool> & /*flags*/,
VectorProxy<Real> & disp,
- const VectorProxy<const Real> & coord) {
+ const VectorProxy<const Real> & coord) override {
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 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;
+ std::cout << "Time step: " << time_step << "\n";
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);
+ for (auto && [pos, vel] : zip(make_view(position, spatial_dimension),
+ make_view(velocity, spatial_dimension))) {
+ vel = loading_rate * pos;
}
model.dump();
Velocity vely(model, VI, _y);
Velocity velx(model, VI, _x);
/// Main loop
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;
+ std::cout << "passing step " << s << "/" << max_steps << "\n";
}
}
return 0;
}
diff --git a/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/images/cohesive_extrinsic_ig_tg.gif b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/images/cohesive_extrinsic_ig_tg.gif
new file mode 100644
index 000000000..f332f6d41
Binary files /dev/null and b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/images/cohesive_extrinsic_ig_tg.gif differ
diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/material.dat b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/material.dat
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic_ig_tg/material.dat
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/material.dat
diff --git a/examples/cohesive_element/cohesive_extrinsic_ig_tg/triangle.geo b/examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/triangle.geo
similarity index 100%
rename from examples/cohesive_element/cohesive_extrinsic_ig_tg/triangle.geo
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_extrinsic_ig_tg/triangle.geo
diff --git a/examples/cohesive_element/cohesive_intrinsic/CMakeLists.txt b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/CMakeLists.txt
similarity index 100%
rename from examples/cohesive_element/cohesive_intrinsic/CMakeLists.txt
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/README.rst b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/README.rst
new file mode 100644
index 000000000..d0885fc5c
--- /dev/null
+++ b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/README.rst
@@ -0,0 +1,51 @@
+cohesive_intrinsic (2D)
+'''''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: cohesive_intrinsic.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/cohesive_intrinsic.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_cohesive_model/`` `cohesive_intrinsic <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/>`_
+
+
+In ``cohesive_intrinsic``, an example of intrinsic cohesive elements is shown.
+An intrinsic simulation is initialized by setting the ``_is_extrinsic`` argument of ``model.initFull`` to ``false``::
+
+ model.initFull(_analysis_method = _explicit_lumped_mass, _is_extrinsic = false);
+
+The cohesive elements are inserted between :math:`x = -0.26` and :math:`x =
+-0.24` before the start of the simulation with
+``model.getElementInserter().setLimit(_x, -0.26, -0.24);``. Elements to the
+right of this limit are moved to the right. The resulting displacement is shown
+in :numref:`fig-smm-cohesive-intrinsic`.
+
+With intrinsic cohesive elements, a bi-linear or exponential cohesive law should
+be used instead of a linear one (see section
+:ref:`sect-smm-intrinsic-insertion`). This is set in the file ``material.dat``::
+
+ material cohesive_bilinear [
+ name = cohesive
+ sigma_c = 1
+ beta = 1.5
+ G_c = 1
+ delta_0 = 0.1
+ penalty = 1e10
+ ]
+
+.. _fig-smm-cohesive-intrinsic:
+.. figure:: examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/images/cohesive_intrinsic.png
+ :align: center
+ :width: 60%
+
+ Displacement in the x direction for the cohesive_intrinsic example.
diff --git a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/cohesive_intrinsic.cc
similarity index 83%
rename from examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/cohesive_intrinsic.cc
index 0c760b0ea..e69dc7cf0 100644
--- a/examples/cohesive_element/cohesive_intrinsic/cohesive_intrinsic.cc
+++ b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/cohesive_intrinsic.cc
@@ -1,127 +1,123 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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);
+static void updateDisplacement(SolidMechanicsModelCohesive & model,
+ const ElementGroup & group, Real increment);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
const Int spatial_dimension = 2;
const Int max_steps = 350;
Mesh mesh(spatial_dimension);
mesh.read("triangle.msh");
SolidMechanicsModelCohesive model(mesh);
+ // To restric the insertion to the range [-0.26, -0.24] in the x direction
model.getElementInserter().setLimit(_x, -0.26, -0.24);
/// model initialization
+ // _is_extrinsic = false for intrinsic
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;
+ std::cout << "Time step: " << time_step << "\n";
Array<bool> & boundary = model.getBlockedDOFs();
Int nb_nodes = mesh.getNbNodes();
/// boundary conditions
- for (Int dim = 0; dim < spatial_dimension; ++dim) {
- for (Int n = 0; n < nb_nodes; ++n) {
- boundary(n, dim) = true;
- }
- }
+ boundary.set(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)
+ if (barycenter(_x) > -0.25) {
elements.add(el, true);
+ }
},
_element_kind = _ek_regular);
Real increment = 0.01;
updateDisplacement(model, elements, increment);
/// Main loop
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;
+ std::cout << "passing step " << s << "/" << max_steps << "\n";
}
}
Real Ed = model.getEnergy("dissipated");
Real Edt = 2 * sqrt(2);
- std::cout << Ed << " " << Edt << std::endl;
+ std::cout << Ed << " " << Edt << "\n";
if (Ed < Edt * 0.999 || Ed > Edt * 1.001 || std::isnan(Ed)) {
- std::cout << "The dissipated energy is incorrect" << std::endl;
- return EXIT_FAILURE;
+ std::cout << "The dissipated energy is incorrect"
+ << "\n";
+ return -1;
}
- finalize();
-
- return EXIT_SUCCESS;
+ return 0;
}
/* -------------------------------------------------------------------------- */
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/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/images/cohesive_intrinsic.png b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/images/cohesive_intrinsic.png
new file mode 100644
index 000000000..de2d30b1d
Binary files /dev/null and b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/images/cohesive_intrinsic.png differ
diff --git a/examples/cohesive_element/cohesive_intrinsic/material.dat b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/material.dat
similarity index 100%
rename from examples/cohesive_element/cohesive_intrinsic/material.dat
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/material.dat
diff --git a/examples/cohesive_element/cohesive_intrinsic/triangle.geo b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/triangle.geo
similarity index 100%
rename from examples/cohesive_element/cohesive_intrinsic/triangle.geo
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/triangle.geo
diff --git a/examples/cohesive_element/cohesive_intrinsic/triangle.msh b/examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/triangle.msh
similarity index 100%
rename from examples/cohesive_element/cohesive_intrinsic/triangle.msh
rename to examples/c++/solid_mechanics_cohesive_model/cohesive_intrinsic/triangle.msh
diff --git a/examples/c++/solid_mechanics_model/CMakeLists.txt b/examples/c++/solid_mechanics_model/CMakeLists.txt
new file mode 100644
index 000000000..a44ebf2a1
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/CMakeLists.txt
@@ -0,0 +1,7 @@
+add_example(new_material "Example on how to add a new material in Akantu" PACKAGE core)
+add_example(boundary_conditions "Example on hoy to set boundary conditions" PACKAGE core)
+add_example(explicit "Example on how to run an explicit simulation" PACKAGE core)
+add_example(io "Example on how to perform Input/Output operations" PACKAGE core)
+add_example(implicit "Example on how to run an implicit simulation" PACKAGE implicit)
+add_example(static "Example on how to run a static simulation" PACKAGE implicit)
+add_example(parallel "Example of how to write a parallel code with Akantu" PACKAGE parallel)
diff --git a/examples/c++/solid_mechanics_model/README.rst b/examples/c++/solid_mechanics_model/README.rst
new file mode 100644
index 000000000..0df8f1235
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/README.rst
@@ -0,0 +1,16 @@
+Solid Mechanics Model
+`````````````````````
+
+.. include:: examples/c++/solid_mechanics_model/explicit/README.rst
+
+.. include:: examples/c++/solid_mechanics_model/implicit/README.rst
+
+.. include:: examples/c++/solid_mechanics_model/static/README.rst
+
+.. include:: examples/c++/solid_mechanics_model/parallel/README.rst
+
+.. include:: examples/c++/solid_mechanics_model/boundary_conditions/README.rst
+
+.. include:: examples/c++/solid_mechanics_model/new_material/README.rst
+
+.. include:: examples/c++/solid_mechanics_model/io/README.rst
diff --git a/examples/boundary_conditions/CMakeLists.txt b/examples/c++/solid_mechanics_model/boundary_conditions/CMakeLists.txt
similarity index 98%
rename from examples/boundary_conditions/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/boundary_conditions/CMakeLists.txt
index 9a21278ad..9bc7e5785 100644
--- a/examples/boundary_conditions/CMakeLists.txt
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/CMakeLists.txt
@@ -1,28 +1,30 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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_example(predefined_bc
"Example of predefined boundary condition" PACKAGE core)
+
add_example(user_defined_bc
"Example of user defined boundary condition" PACKAGE core)
+
add_example(python_user_defined_bc
- "Example of python user defined boundary condition" PACKAGE pybind11)
+ "Example of python user defined boundary condition" PACKAGE python_interface)
diff --git a/examples/c++/solid_mechanics_model/boundary_conditions/README.rst b/examples/c++/solid_mechanics_model/boundary_conditions/README.rst
new file mode 100644
index 000000000..83c3e2d3f
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/README.rst
@@ -0,0 +1,45 @@
+Boundary conditions usage (2D)
+''''''''''''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: predefined_bc.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/predefined_bc.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: user_defined_bc.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/user_defined_bc.cc
+ :language: c++
+ :lines: 20-
+
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/`` `boundary_conditions <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/boundary_conditions>`_
+
+In ``predefined_bc`` it is shown how to impose Dirichlet boundary condition
+using the predefined ``BC::Dirichlet::FixedValue``
+(:numref:`fig-ex-predefined_bc`). Three built-in Dirichlet functors exist:
+``FixedValue``, ``FlagOnly`` and ``IncrementValue``.
+
+.. _fig-ex-predefined_bc:
+.. figure:: examples/c++/solid_mechanics_model/boundary_conditions/images/predefined_bc.svg
+ :align: center
+
+ Dirichlet boundary conditions for the predifined_bc case.
+
+To define another functor, a class inherited from
+``BC::Dirichlet::DirichletFunctor`` can be created as illustrated in the example
+``user_defined_bc`` where a sinusoidal BC is imposed. The corresponding
+sinusoidal displacement is depicted in :numref:`fig-ex-user_defined_bc`. Note
+that a Neumann BC is also imposed.
+
+.. _fig-ex-user_defined_bc:
+.. figure:: examples/c++/solid_mechanics_model/boundary_conditions/images/user_defined_bc_displ_mag.png
+ :align: center
+ :width: 60%
+
+ Displacement magnitude for the user_defined_bc example.
diff --git a/examples/c++/solid_mechanics_model/boundary_conditions/images/predefined_bc.svg b/examples/c++/solid_mechanics_model/boundary_conditions/images/predefined_bc.svg
new file mode 100644
index 000000000..fef8b5876
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/images/predefined_bc.svg
@@ -0,0 +1,457 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="115.303mm"
+ height="96.556938mm"
+ viewBox="0 0 115.30302 96.556938"
+ version="1.1"
+ id="svg5"
+ xml:space="preserve"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="predefined_bc.svg"
+ inkscape:export-filename="static_BC.svg"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview7"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false"
+ inkscape:lockguides="true"
+ inkscape:zoom="1.829812"
+ inkscape:cx="368.6171"
+ inkscape:cy="291.28675"
+ inkscape:window-width="2560"
+ inkscape:window-height="1371"
+ inkscape:window-x="0"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g97" /><defs
+ id="defs2"><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient7100"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7098" /></linearGradient><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-35.991445,-11.538894)"><g
+ id="g97"
+ transform="matrix(0.14352268,0,0,0.11578455,-27.258384,1.4003671)"><circle
+ fill="#5a5a5a"
+ cx="516.78601"
+ cy="823.71399"
+ r="2"
+ id="circle81" /><circle
+ fill="#5a5a5a"
+ cx="1203.21"
+ cy="823.71399"
+ r="2"
+ id="circle83" /><circle
+ fill="#5a5a5a"
+ cx="1203.21"
+ cy="137.286"
+ r="2"
+ id="circle85" /><circle
+ fill="#5a5a5a"
+ cx="516.78601"
+ cy="137.286"
+ r="2"
+ id="circle87" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="516.786,823.714 1203.21,823.714 1203.21,137.286 516.786,137.286 516.786,823.714"
+ id="polyline89"
+ style="stroke-width:4.32861;stroke-dasharray:none" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1690,921"
+ id="polyline91" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1660,891"
+ id="polyline93" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1660,921"
+ id="polyline95" /></g><g
+ id="g4256"
+ transform="matrix(0.23733616,0,0,0.27167982,10.209103,-49.889664)"><g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" /></g></g><g
+ id="g4256-36"
+ transform="matrix(0.23733616,0,0,0.27167982,10.467344,29.661108)"><g
+ id="g2882-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62" /></g></g><g
+ id="g4256-36-8"
+ transform="matrix(0,-0.23733616,0.27167982,0,-20.517226,132.70406)"><g
+ id="g2882-7-9"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4" /></g></g><g
+ id="g4256-36-8-4"
+ transform="matrix(0,-0.23733616,0.27167982,0,28.064012,132.70404)"><g
+ id="g2882-7-9-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7" /></g></g><g
+ id="g4256-36-8-5"
+ transform="matrix(0,-0.23733616,0.27167982,0,78.112869,132.70404)"><g
+ id="g2882-7-9-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5" /></g></g><g
+ id="g4256-36-6"
+ transform="matrix(0.23733616,0,0,0.27167982,10.302838,-10.270631)"><g
+ id="g2882-7-1"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-7"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-2"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-2" /></g></g></g></svg>
diff --git a/examples/c++/solid_mechanics_model/boundary_conditions/images/user_defined_bc_displ_mag.png b/examples/c++/solid_mechanics_model/boundary_conditions/images/user_defined_bc_displ_mag.png
new file mode 100644
index 000000000..2d41c01a1
Binary files /dev/null and b/examples/c++/solid_mechanics_model/boundary_conditions/images/user_defined_bc_displ_mag.png differ
diff --git a/examples/boundary_conditions/predefined_bc/CMakeLists.txt b/examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/CMakeLists.txt
similarity index 100%
rename from examples/boundary_conditions/predefined_bc/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/CMakeLists.txt
diff --git a/examples/boundary_conditions/predefined_bc/material.dat b/examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/material.dat
similarity index 100%
rename from examples/boundary_conditions/predefined_bc/material.dat
rename to examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/material.dat
diff --git a/examples/boundary_conditions/predefined_bc/predefined_bc.cc b/examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/predefined_bc.cc
similarity index 97%
rename from examples/boundary_conditions/predefined_bc/predefined_bc.cc
rename to examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/predefined_bc.cc
index b1ac57964..f901de93a 100644
--- a/examples/boundary_conditions/predefined_bc/predefined_bc.cc
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/predefined_bc.cc
@@ -1,52 +1,51 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
Mesh mesh(2);
mesh.read("square.msh");
// model initialization
SolidMechanicsModel model(mesh);
model.initFull();
// Dirichlet boundary conditions
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x), "Fixed_x");
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y), "Fixed_y");
// output in a paraview file
model.setBaseName("plate");
model.addDumpFieldVector("displacement");
model.addDumpField("blocked_dofs");
model.addDumpField("external_force");
model.dump();
- finalize();
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/boundary_conditions/predefined_bc/square.geo b/examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/square.geo
similarity index 100%
rename from examples/boundary_conditions/predefined_bc/square.geo
rename to examples/c++/solid_mechanics_model/boundary_conditions/predefined_bc/square.geo
diff --git a/examples/boundary_conditions/python_user_defined_bc/CMakeLists.txt b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/CMakeLists.txt
similarity index 100%
rename from examples/boundary_conditions/python_user_defined_bc/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/CMakeLists.txt
diff --git a/examples/boundary_conditions/python_user_defined_bc/boundary_condition.py b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/boundary_condition.py
similarity index 99%
rename from examples/boundary_conditions/python_user_defined_bc/boundary_condition.py
rename to examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/boundary_condition.py
index 20b8ae9a1..0dc49c4e9 100644
--- a/examples/boundary_conditions/python_user_defined_bc/boundary_condition.py
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/boundary_condition.py
@@ -1,20 +1,19 @@
#!/usr/bin/env python3
__copyright__ = (
"Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)"
"Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)"
)
__license__ = "LGPLv3"
import math
class SinBoundary:
-
def __init__(self, amplitude, phase):
self.amplitude = amplitude
self.phase = phase
def compute(self, disp, coord, flags):
disp[1] = - self.amplitude * math.sin(self.phase * coord[1])
flags[1] = True
diff --git a/examples/boundary_conditions/python_user_defined_bc/fine_mesh.geo b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/fine_mesh.geo
similarity index 100%
rename from examples/boundary_conditions/python_user_defined_bc/fine_mesh.geo
rename to examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/fine_mesh.geo
diff --git a/examples/boundary_conditions/python_user_defined_bc/material.dat b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/material.dat
similarity index 100%
rename from examples/boundary_conditions/python_user_defined_bc/material.dat
rename to examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/material.dat
diff --git a/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
similarity index 86%
rename from examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
rename to examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
index 2b20b484b..4a52ef567 100644
--- a/examples/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/python_user_defined_bc/python_user_defined_bc.cc
@@ -1,86 +1,85 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 {
+ inline void operator()(Idx /*node*/, VectorProxy<bool> & flags,
+ VectorProxy<Real> & primal,
+ const VectorProxy<const Real> & coord) override {
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{};
- Int spatial_dimension = 2;
+ const 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, spatial_dimension> traction;
+ traction.set(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;
+ return 0;
}
diff --git a/examples/boundary_conditions/user_defined_bc/CMakeLists.txt b/examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/CMakeLists.txt
similarity index 100%
rename from examples/boundary_conditions/user_defined_bc/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/CMakeLists.txt
diff --git a/examples/boundary_conditions/user_defined_bc/fine_mesh.geo b/examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/fine_mesh.geo
similarity index 100%
rename from examples/boundary_conditions/user_defined_bc/fine_mesh.geo
rename to examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/fine_mesh.geo
diff --git a/examples/boundary_conditions/user_defined_bc/material.dat b/examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/material.dat
similarity index 100%
rename from examples/boundary_conditions/user_defined_bc/material.dat
rename to examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/material.dat
diff --git a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc b/examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/user_defined_bc.cc
similarity index 97%
rename from examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
rename to examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/user_defined_bc.cc
index 8d975d462..66b639890 100644
--- a/examples/boundary_conditions/user_defined_bc/user_defined_bc.cc
+++ b/examples/c++/solid_mechanics_model/boundary_conditions/user_defined_bc/user_defined_bc.cc
@@ -1,78 +1,76 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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()(Idx /*node*/, VectorProxy<bool> & flags,
VectorProxy<Real> & primal,
- const VectorProxy<const Real> & coord) {
+ const VectorProxy<const Real> & coord) override {
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);
Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("fine_mesh.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull();
/// boundary conditions
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;
+ return 0;
}
diff --git a/examples/explicit/CMakeLists.txt b/examples/c++/solid_mechanics_model/explicit/CMakeLists.txt
similarity index 100%
rename from examples/explicit/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/explicit/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_model/explicit/README.rst b/examples/c++/solid_mechanics_model/explicit/README.rst
new file mode 100644
index 000000000..b313c55e9
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/explicit/README.rst
@@ -0,0 +1,55 @@
+explicit (3D)
+'''''''''''''
+
+:Sources:
+
+ .. collapse:: explicit_dynamic.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/explicit/explicit_dynamic.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/explicit/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/`` `explicit <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/explicit>`_
+
+
+In ``explicit``, an example of a 3D dynamic solution with an explicit time integration is shown.
+The explicit scheme is selected using the ``_explicit_lumped_mass`` constant::
+
+ model.initFull(_analysis_method = _explicit_lumped_mass);
+
+Note that it is also the default value, hence using ``model.initFull();`` is equivalent.
+
+This example models the propagation of a wave in a 3D steel beam. The beam and
+the applied displacement in the :math:`x` direction are shown in
+:numref:`fig-smm-explicit-bc`.
+
+.. _fig-smm-explicit-bc:
+.. figure:: examples/c++/solid_mechanics_model/explicit/images/explicit.svg
+ :align: center
+ :width: 90%
+
+ Numerical setup.
+
+The length and height of the beam are :math:`L={10}\mathrm{m}` and :math:`h =
+{1}\mathrm{m}`, respectively. The material is linear elastic, homogeneous and
+isotropic (density: :math:`{7800}\mathrm{kg}/\mathrm{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}\mathrm{m}`. The potential, kinetic and total energies are
+computed. The safety factor is equal to :math:`0.8`.
+
+The dynamic solution is depicted in :numref:`fig-smm-explicit-disp`.
+
+.. _fig-smm-explicit-disp:
+.. figure:: examples/c++/solid_mechanics_model/explicit/images/bar_pulse.gif
+ :align: center
+ :width: 100%
+
+ Dynamic solution: lateral displacement.
diff --git a/examples/explicit/bar.geo b/examples/c++/solid_mechanics_model/explicit/bar.geo
similarity index 100%
rename from examples/explicit/bar.geo
rename to examples/c++/solid_mechanics_model/explicit/bar.geo
diff --git a/examples/explicit/explicit_dynamic.cc b/examples/c++/solid_mechanics_model/explicit/explicit_dynamic.cc
similarity index 94%
rename from examples/explicit/explicit_dynamic.cc
rename to examples/c++/solid_mechanics_model/explicit/explicit_dynamic.cc
index cbc98f7df..f8fa9ba76 100644
--- a/examples/explicit/explicit_dynamic.cc
+++ b/examples/c++/solid_mechanics_model/explicit/explicit_dynamic.cc
@@ -1,98 +1,92 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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>
+#include <solid_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material.dat", argc, argv);
const Int spatial_dimension = 3;
const Real pulse_width = 2.;
const Real A = 0.01;
Real time_step;
Real time_factor = 0.8;
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 (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 (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/c++/solid_mechanics_model/explicit/images/bar_pulse.gif b/examples/c++/solid_mechanics_model/explicit/images/bar_pulse.gif
new file mode 100644
index 000000000..1447d432a
Binary files /dev/null and b/examples/c++/solid_mechanics_model/explicit/images/bar_pulse.gif differ
diff --git a/examples/c++/solid_mechanics_model/explicit/images/explicit.svg b/examples/c++/solid_mechanics_model/explicit/images/explicit.svg
new file mode 100644
index 000000000..bac613bf4
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/explicit/images/explicit.svg
@@ -0,0 +1,2330 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="342.71356pt"
+ height="107.73483pt"
+ viewBox="0 0 342.71356 107.73483"
+ version="1.2"
+ id="svg4483"
+ sodipodi:docname="explicit.svg"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+ <metadata
+ id="metadata4487">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1152"
+ id="namedview4485"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="1.6819299"
+ inkscape:cx="243.66869"
+ inkscape:cy="9.2156239"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg4483" />
+ <defs
+ id="defs646">
+ <g
+ id="g644">
+ <symbol
+ overflow="visible"
+ id="glyph0-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path2"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.46875,-5.4375 H 0.8125 L 1,-6.046875 C 1.125,-6.40625 1.8125,-6.78125 2.375,-6.78125 c 0.71875,0 1.296875,0.578125 1.296875,1.265625 0,0.8125 -0.65625,1.5 -1.421875,1.5 -0.09375,0 -0.203125,-0.015625 -0.359375,-0.015625 l -0.15625,-0.015625 -0.125,0.578125 0.0625,0.0625 c 0.421875,-0.1875 0.625,-0.234375 0.921875,-0.234375 0.90625,0 1.4375,0.578125 1.4375,1.5625 0,1.125 -0.671875,1.84375 -1.6875,1.84375 -0.5,0 -0.953125,-0.15625 -1.28125,-0.46875 C 0.8125,-0.9375 0.671875,-1.1875 0.453125,-1.78125 L 0.15625,-1.671875 C 0.390625,-1 0.484375,-0.609375 0.546875,-0.0625 1.125,0.125 1.609375,0.21875 2,0.21875 c 0.875,0 1.875,-0.484375 2.484375,-1.21875 0.375,-0.453125 0.546875,-0.9375 0.546875,-1.4375 0,-0.53125 -0.203125,-0.984375 -0.609375,-1.265625 -0.265625,-0.1875 -0.515625,-0.28125 -1.0625,-0.375 C 4.234375,-4.75 4.5625,-5.25 4.5625,-5.90625 4.5625,-6.875 3.75,-7.515625 2.546875,-7.515625 c -0.75,0 -1.234375,0.203125 -1.765625,0.734375 z m 0,0"
+ id="path5"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.171875,-0.25 V 0.03125 C 2.21875,0 2.21875,0 2.609375,0 3,0 3,0 5.109375,0.03125 5.078125,-0.203125 5.078125,-0.3125 5.078125,-0.453125 c 0,-0.140625 0,-0.25 0.03125,-0.5 -1.265625,0.0625 -1.765625,0.0625 -3.78125,0.109375 L 3.3125,-2.9375 c 1.0625,-1.125 1.390625,-1.734375 1.390625,-2.546875 0,-1.25 -0.859375,-2.03125 -2.234375,-2.03125 -0.796875,0 -1.328125,0.21875 -1.859375,0.765625 l -0.1875,1.484375 h 0.3125 l 0.15625,-0.5 c 0.171875,-0.640625 0.5625,-0.90625 1.296875,-0.90625 0.9375,0 1.53125,0.59375 1.53125,1.515625 0,0.8125 -0.453125,1.625 -1.6875,2.9375 z m 0,0"
+ id="path8"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 2.78125,-7.015625 c 0.03125,0.375 0.046875,0.625 0.046875,1.09375 V -1.3125 c 0,0.859375 -0.0625,0.953125 -0.5625,0.984375 L 1.75,-0.296875 V 0.03125 C 2.390625,0.015625 2.765625,0 3.34375,0 3.90625,0 4.296875,0.015625 4.9375,0.03125 v -0.328125 l -0.515625,-0.03125 c -0.5,-0.03125 -0.5625,-0.125 -0.5625,-0.984375 v -4.609375 c 0,-0.484375 0.015625,-0.734375 0.046875,-1.09375 h 1.6875 c 0.3125,0 0.421875,0.09375 0.4375,0.359375 l 0.046875,0.859375 H 6.40625 c 0,-0.703125 0.03125,-1.125 0.078125,-1.75 C 5.703125,-7.53125 5.34375,-7.53125 5.03125,-7.53125 4.609375,-7.515625 4.296875,-7.515625 4.140625,-7.515625 H 2.40625 c -0.109375,0 -0.6875,-0.015625 -1.46875,-0.015625 L 0.203125,-7.546875 c 0.046875,0.625 0.0625,1.046875 0.0625,1.75 h 0.34375 L 0.65625,-6.65625 c 0.015625,-0.265625 0.125,-0.359375 0.4375,-0.359375 z m 0,0"
+ id="path11"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.078125,-7.203125 H 0.6875 c 0.203125,0 0.265625,0.109375 0.265625,0.4375 v 5.65625 c 0,0.6875 -0.03125,0.765625 -0.390625,0.78125 l -0.5,0.03125 V 0.03125 C 0.8125,0.015625 1.09375,0 1.421875,0 1.734375,0 2.03125,0.015625 2.765625,0.03125 V -0.296875 L 2.28125,-0.328125 C 1.90625,-0.34375 1.875,-0.421875 1.875,-1.109375 v -2.3125 c 0,-0.5 0.71875,-1.03125 1.390625,-1.03125 0.71875,0 1.203125,0.546875 1.203125,1.390625 V 0.03125 C 5.140625,0 5.140625,0 5.328125,0 c 0.15625,0 0.15625,0 0.90625,0.03125 v -0.328125 l -0.4375,-0.03125 c -0.375,-0.015625 -0.40625,-0.09375 -0.40625,-0.78125 V -3.21875 c 0,-1.28125 -0.609375,-1.890625 -1.828125,-1.890625 -0.40625,0 -0.625,0.078125 -0.859375,0.265625 L 1.875,-4.125 v -3.703125 l -0.09375,-0.09375 c -0.484375,0.1875 -0.84375,0.28125 -1.703125,0.40625 z m 0,0"
+ id="path14"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.765625,-0.765625 4.625,-0.875 c -0.703125,0.421875 -0.953125,0.515625 -1.421875,0.515625 -0.703125,0 -1.296875,-0.3125 -1.59375,-0.84375 -0.21875,-0.375 -0.296875,-0.671875 -0.3125,-1.3125 h 1.59375 c 0.75,0 1.21875,-0.03125 1.96875,-0.140625 0.015625,-0.15625 0.03125,-0.25 0.03125,-0.390625 0,-1.25 -0.8125,-2.0625 -2.03125,-2.0625 -0.40625,0 -0.875,0.140625 -1.328125,0.390625 -0.890625,0.515625 -1.25,1.203125 -1.25,2.328125 0,0.6875 0.171875,1.28125 0.453125,1.6875 C 1.171875,-0.125 1.90625,0.21875 2.71875,0.21875 3.125,0.21875 3.53125,0.125 3.984375,-0.0625 4.28125,-0.1875 4.5,-0.328125 4.546875,-0.390625 Z M 3.921875,-2.90625 C 3.34375,-2.890625 3.09375,-2.875 2.6875,-2.875 c -0.5,0 -0.78125,-0.015625 -1.375,-0.0625 0,-0.515625 0.046875,-0.765625 0.1875,-1.046875 C 1.734375,-4.453125 2.203125,-4.75 2.71875,-4.75 c 0.375,0 0.65625,0.140625 0.84375,0.4375 0.25,0.359375 0.3125,0.671875 0.359375,1.40625 z m 0,0"
+ id="path17"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 2.046875,-5.078125 -0.09375,-0.03125 c -0.5625,0.21875 -1.125,0.375 -1.703125,0.4375 v 0.3125 h 0.40625 c 0.4375,0 0.484375,0.078125 0.484375,0.796875 v 2.453125 c 0,0.6875 -0.046875,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.3125,0 1.3125,0 1.59375,0 1.859375,0 1.859375,0 2.953125,0.03125 v -0.328125 l -0.5,-0.03125 c -0.375,-0.015625 -0.40625,-0.09375 -0.40625,-0.78125 z M 1.546875,-7.5 C 1.21875,-7.5 0.9375,-7.203125 0.9375,-6.875 c 0,0.3125 0.28125,0.59375 0.59375,0.59375 0.328125,0 0.625,-0.28125 0.625,-0.59375 0,-0.3125 -0.296875,-0.625 -0.609375,-0.625 z m 0,0"
+ id="path20"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.46875,0.03125 C 5.140625,0 5.140625,0 5.328125,0 c 0.15625,0 0.15625,0 0.90625,0.03125 v -0.328125 l -0.4375,-0.03125 c -0.375,-0.015625 -0.40625,-0.09375 -0.40625,-0.78125 V -3.21875 c 0,-1.28125 -0.609375,-1.890625 -1.828125,-1.890625 -0.40625,0 -0.625,0.078125 -0.859375,0.265625 L 1.875,-4.125 v -0.953125 l -0.09375,-0.03125 c -0.5625,0.21875 -1.125,0.375 -1.703125,0.4375 v 0.3125 h 0.40625 c 0.4375,0 0.46875,0.078125 0.46875,0.796875 v 2.453125 c 0,0.6875 -0.03125,0.765625 -0.390625,0.78125 l -0.5,0.03125 V 0.03125 C 0.8125,0.015625 1.09375,0 1.421875,0 1.734375,0 2.03125,0.015625 2.765625,0.03125 V -0.296875 L 2.28125,-0.328125 C 1.90625,-0.34375 1.875,-0.421875 1.875,-1.109375 v -2.3125 c 0,-0.5 0.71875,-1.03125 1.390625,-1.03125 0.71875,0 1.203125,0.546875 1.203125,1.390625 z m 0,0"
+ id="path23"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-8"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.0625,-4.171875 v 3.140625 c 0,0.8125 0.359375,1.15625 1.203125,1.15625 0.25,0 0.515625,-0.046875 0.578125,-0.125 L 3.375,-0.578125 3.234375,-0.765625 c -0.28125,0.15625 -0.4375,0.203125 -0.65625,0.203125 -0.421875,0 -0.59375,-0.21875 -0.59375,-0.75 V -4.171875 H 3.375 L 3.484375,-4.75 l -1.5,0.0625 v -0.421875 c 0,-0.453125 0.03125,-0.84375 0.125,-1.546875 L 1.96875,-6.765625 c -0.25,0.15625 -0.578125,0.296875 -0.921875,0.40625 C 1.078125,-6.03125 1.09375,-5.828125 1.09375,-5.5 v 0.765625 l -0.859375,0.375 V -4.125 Z m 0,0"
+ id="path26"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-9"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.53125,-0.890625 3.484375,0.03125 C 4.1875,0 4.1875,0 4.328125,0 c 0.0625,0 0.328125,0.015625 0.8125,0.03125 V -0.296875 L 4.71875,-0.3125 C 4.453125,-0.328125 4.40625,-0.421875 4.40625,-0.953125 V -2.9375 c 0,-1.59375 -0.453125,-2.171875 -1.71875,-2.171875 C 2.21875,-5.109375 1.78125,-5 1.359375,-4.75 L 0.78125,-4.390625 V -3.6875 l 0.28125,0.078125 0.140625,-0.34375 c 0.234375,-0.5 0.34375,-0.578125 0.84375,-0.578125 1.03125,0 1.453125,0.390625 1.484375,1.390625 L 2.453125,-2.9375 C 0.96875,-2.671875 0.34375,-2.15625 0.34375,-1.203125 c 0,0.84375 0.515625,1.328125 1.375,1.328125 0.203125,0 0.390625,-0.03125 0.46875,-0.078125 z m 0,-0.46875 c -0.3125,0.453125 -1,0.875 -1.421875,0.875 -0.4375,0 -0.828125,-0.40625 -0.828125,-0.875 0,-0.40625 0.21875,-0.796875 0.546875,-1 0.28125,-0.15625 0.875,-0.3125 1.703125,-0.4375 z m 0,0"
+ id="path29"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-10"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.25,-7.203125 h 0.609375 c 0.203125,0 0.28125,0.109375 0.28125,0.4375 v 5.65625 c 0,0.6875 -0.046875,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.3125,0 1.3125,0 1.59375,0 1.859375,0 1.859375,0 2.953125,0.03125 v -0.328125 l -0.5,-0.03125 c -0.375,-0.015625 -0.40625,-0.09375 -0.40625,-0.78125 v -6.71875 l -0.09375,-0.09375 c -0.484375,0.1875 -0.84375,0.28125 -1.703125,0.40625 z m 0,0"
+ id="path32"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-11"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.5,-4.765625 c -0.625,-0.265625 -0.921875,-0.34375 -1.296875,-0.34375 -0.296875,0 -0.5625,0.0625 -0.84375,0.203125 l -0.953125,0.5 c -0.625,0.328125 -1.03125,1.125 -1.03125,2.046875 0,0.875 0.296875,1.59375 0.828125,2.03125 0.375,0.3125 0.890625,0.453125 1.59375,0.453125 0.21875,0 0.46875,-0.03125 0.53125,-0.078125 l 1.203125,-1.015625 -0.046875,1 C 5.015625,0.015625 5.1875,0 5.328125,0 5.40625,0 5.5625,0 5.796875,0.015625 c 0.078125,0 0.28125,0 0.515625,0.015625 v -0.328125 l -0.5,-0.03125 C 5.4375,-0.34375 5.40625,-0.421875 5.40625,-1.109375 v -6.71875 L 5.3125,-7.921875 c -0.484375,0.1875 -0.84375,0.28125 -1.703125,0.40625 v 0.3125 H 4.21875 c 0.203125,0 0.28125,0.109375 0.28125,0.4375 z m 0,2.359375 c 0,0.703125 -0.03125,0.8125 -0.171875,1.0625 -0.296875,0.515625 -0.84375,0.859375 -1.34375,0.859375 -0.96875,0 -1.65625,-0.9375 -1.65625,-2.234375 0,-1.1875 0.59375,-1.890625 1.578125,-1.890625 0.40625,0 0.84375,0.15625 1.234375,0.40625 C 4.359375,-4.046875 4.5,-3.90625 4.5,-3.8125 Z m 0,0"
+ id="path35"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-12"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.453125,-1.5625 c 0,0.75 -0.03125,1.078125 -0.125,1.515625 0.5625,0.1875 0.984375,0.265625 1.5,0.265625 1.421875,0 2.4375,-0.765625 2.4375,-1.828125 0,-0.34375 -0.09375,-0.59375 -0.3125,-0.8125 C 3.671875,-2.6875 3.3125,-2.828125 2.359375,-3.015625 1.46875,-3.1875 1.171875,-3.40625 1.171875,-3.90625 1.171875,-4.453125 1.546875,-4.75 2.21875,-4.75 2.9375,-4.75 3.5,-4.375 3.5,-3.859375 v 0.25 H 3.8125 C 3.8125,-4.25 3.828125,-4.5 3.859375,-4.84375 3.28125,-5.03125 2.890625,-5.109375 2.4375,-5.109375 c -1.265625,0 -2.03125,0.59375 -2.03125,1.578125 0,0.515625 0.234375,0.890625 0.734375,1.125 0.296875,0.125 0.875,0.296875 1.625,0.46875 0.484375,0.109375 0.6875,0.328125 0.6875,0.75 0,0.59375 -0.546875,1 -1.3125,1 -0.796875,0 -1.359375,-0.375 -1.359375,-0.921875 V -1.5625 Z m 0,0"
+ id="path38"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-13"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.109375,-4.359375 h 0.40625 C 0.953125,-4.359375 1,-4.28125 1,-3.5625 V 1.921875 C 1,2.609375 0.953125,2.6875 0.59375,2.703125 l -0.5,0.03125 V 3.0625 C 1.171875,3.03125 1.171875,3.03125 1.453125,3.03125 c 0.265625,0 0.265625,0 1.359375,0.03125 V 2.734375 l -0.5,-0.03125 C 1.9375,2.6875 1.90625,2.609375 1.90625,1.921875 v -2.0625 C 2.234375,0.046875 2.578125,0.125 3.078125,0.125 c 0.3125,0 0.59375,-0.0625 0.765625,-0.171875 l 1.25,-0.796875 c 0.4375,-0.296875 0.953125,-1.40625 0.953125,-2.109375 0,-1.21875 -1.015625,-2.15625 -2.265625,-2.15625 C 3.375,-5.109375 2.984375,-5 2.796875,-4.84375 L 1.90625,-4.03125 V -5.078125 L 1.8125,-5.109375 c -0.5625,0.21875 -1.125,0.375 -1.703125,0.4375 z M 1.90625,-3.34375 c 0,-0.140625 0.0625,-0.265625 0.203125,-0.453125 0.3125,-0.40625 0.765625,-0.609375 1.296875,-0.609375 1.03125,0 1.6875,0.71875 1.6875,1.859375 0,1.21875 -0.734375,2.125 -1.71875,2.125 -0.59375,0 -1.046875,-0.203125 -1.46875,-0.640625 z m 0,0"
+ id="path41"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-14"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.359375,-3.390625 c 0,-0.5 0.046875,-0.953125 0.140625,-1.34375 -0.4375,-0.265625 -0.8125,-0.375 -1.265625,-0.375 -0.515625,0 -1.125,0.203125 -1.78125,0.609375 -0.765625,0.484375 -1.171875,1.25 -1.171875,2.203125 0,1.484375 1.03125,2.515625 2.5,2.515625 0.5625,0 1.390625,-0.203125 1.5,-0.375 L 4.5,-0.5 4.390625,-0.671875 c -0.40625,0.21875 -0.75,0.328125 -1.140625,0.328125 -1.203125,0 -2,-0.9375 -2,-2.375 0,-1.171875 0.53125,-1.828125 1.515625,-1.828125 0.484375,0 1.015625,0.21875 1.203125,0.484375 l 0.078125,0.671875 z m 0,0"
+ id="path44"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-15"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.203125,-4.359375 H 0.59375 c 0.4375,0 0.484375,0.078125 0.484375,0.796875 v 2.453125 c 0,0.6875 -0.03125,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.21875,0 1.25,0 1.5625,0 1.859375,0 2.15625,0.015625 2.859375,0.03125 V -0.296875 L 2.40625,-0.328125 C 2.03125,-0.34375 2,-0.421875 2,-1.109375 v -2.3125 c 0,-0.5 0.71875,-1.03125 1.375,-1.03125 0.578125,0 0.984375,0.5625 0.984375,1.390625 v 1.953125 c 0,0.6875 -0.03125,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 4.546875,0 4.546875,0 4.828125,0 5.09375,0 5.09375,0 6.1875,0.03125 v -0.328125 l -0.5,-0.03125 C 5.3125,-0.34375 5.28125,-0.421875 5.28125,-1.109375 v -2.3125 c 0,-0.5 0.71875,-1.03125 1.375,-1.03125 0.578125,0 0.984375,0.5625 0.984375,1.390625 V 0.03125 C 8.3125,0 8.328125,0 8.5,0 8.65625,0 8.65625,0 9.484375,0.03125 V -0.296875 L 8.96875,-0.328125 C 8.59375,-0.34375 8.5625,-0.421875 8.5625,-1.109375 v -2.25 c 0,-1.078125 -0.640625,-1.75 -1.640625,-1.75 -0.375,0 -0.6875,0.09375 -0.890625,0.265625 l -0.828125,0.75 C 4.859375,-4.828125 4.40625,-5.109375 3.65625,-5.109375 3.25,-5.109375 2.9375,-5.015625 2.75,-4.84375 L 2,-4.140625 v -0.9375 l -0.109375,-0.03125 c -0.546875,0.21875 -1.109375,0.375 -1.6875,0.4375 z m 0,0"
+ id="path47"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-16"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.875,-4.703125 V -5 c -0.65625,0.015625 -0.84375,0.03125 -1.015625,0.03125 -0.1875,0 -0.375,-0.015625 -1.03125,-0.03125 v 0.296875 l 0.453125,0.03125 c 0.171875,0 0.25,0.109375 0.25,0.28125 0,0.171875 -0.078125,0.46875 -0.203125,0.796875 L 3.875,-2.4375 C 3.734375,-2.125 3.609375,-1.828125 3.203125,-0.921875 L 1.890625,-4.0625 c -0.0625,-0.140625 -0.09375,-0.296875 -0.09375,-0.40625 0,-0.125 0.09375,-0.203125 0.28125,-0.203125 l 0.53125,-0.03125 V -5 C 1.53125,-4.96875 1.53125,-4.96875 1.328125,-4.96875 1.125,-4.96875 0.59375,-4.984375 0.0625,-5 v 0.296875 l 0.375,0.03125 C 0.59375,-4.65625 0.65625,-4.59375 0.78125,-4.3125 l 1.875,4.390625 h 0.546875 c 0.0625,-0.1875 0.171875,-0.46875 0.171875,-0.5 0.109375,-0.3125 0.25,-0.6875 0.265625,-0.6875 l 1.28125,-2.84375 c 0.25,-0.5 0.40625,-0.703125 0.625,-0.71875 z m 0,0"
+ id="path50"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-17"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.046875,-5.109375 c -1.59375,0 -2.703125,1.125 -2.703125,2.75 0,1.53125 0.96875,2.578125 2.375,2.578125 1.6875,0 2.890625,-1.171875 2.890625,-2.796875 0,-1.484375 -1.078125,-2.53125 -2.5625,-2.53125 z M 2.84375,-4.75 c 1,0 1.75,1.078125 1.75,2.5625 0,1.265625 -0.5625,2.046875 -1.4375,2.046875 -1.078125,0 -1.796875,-1.046875 -1.796875,-2.59375 0,-1.3125 0.53125,-2.015625 1.484375,-2.015625 z m 0,0"
+ id="path53"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-18"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.234375,-0.9375 C 3,-1.359375 2.875,-1.609375 2.6875,-2.140625 L 1.984375,-3.96875 C 1.921875,-4.15625 1.875,-4.3125 1.875,-4.421875 c 0,-0.15625 0.125,-0.25 0.375,-0.25 l 0.40625,-0.03125 V -5 C 1.609375,-4.96875 1.609375,-4.96875 1.390625,-4.96875 1.1875,-4.96875 1.1875,-4.96875 0.125,-5 v 0.296875 l 0.203125,0.03125 c 0.265625,0.03125 0.40625,0.140625 0.5625,0.53125 l 1.1875,2.859375 c 0.3125,0.734375 0.421875,1 0.609375,1.546875 l -0.25,0.65625 c -0.34375,0.921875 -0.765625,1.4375 -1.1875,1.4375 -0.171875,0 -0.359375,-0.09375 -0.546875,-0.25 H 0.5625 l -0.265625,0.8125 C 0.5,3.03125 0.671875,3.09375 0.890625,3.09375 1.609375,3.09375 2.078125,2.6875 2.5,1.75 l 2.21875,-5.109375 c 0.421875,-1 0.640625,-1.28125 0.90625,-1.3125 l 0.3125,-0.03125 V -5 c -0.859375,0.03125 -0.859375,0.03125 -1.046875,0.03125 -0.171875,0 -0.171875,0 -1.03125,-0.03125 v 0.296875 l 0.28125,0.03125 c 0.3125,0.015625 0.46875,0.109375 0.46875,0.265625 0,0.078125 -0.03125,0.171875 -0.078125,0.28125 z m 0,0"
+ id="path56"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-19"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.71875,-7.8125 c -0.234375,-0.09375 -0.359375,-0.125 -0.5,-0.125 -0.34375,0 -0.734375,0.1875 -0.96875,0.453125 l -0.640625,0.71875 C 1.296875,-6.40625 1.15625,-5.90625 1.15625,-5.1875 v 0.453125 l -0.75,0.34375 v 0.234375 l 0.75,-0.046875 v 3.09375 c 0,0.6875 -0.03125,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.34375,0 1.34375,0 1.625,0 1.890625,0 2.1875,0.015625 3.046875,0.03125 V -0.296875 L 2.46875,-0.328125 C 2.109375,-0.34375 2.078125,-0.421875 2.078125,-1.109375 v -3.09375 H 3.3125 l 0.078125,-0.578125 -1.3125,0.046875 V -5.65625 c 0,-1.265625 0.140625,-1.5625 0.75,-1.5625 0.296875,0 0.5,0.078125 0.765625,0.296875 l 0.125,-0.0625 z M 5.5,-5.03125 5.40625,-5.109375 C 4.921875,-4.875 4.34375,-4.71875 3.703125,-4.640625 V -4.34375 H 4.09375 c 0.4375,0 0.484375,0.078125 0.484375,0.796875 v 2.4375 c 0,0.6875 -0.03125,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 4.765625,0 4.765625,0 5.03125,0 5.3125,0 5.3125,0 6.40625,0.03125 v -0.328125 l -0.5,-0.03125 C 5.53125,-0.34375 5.5,-0.421875 5.5,-1.109375 Z M 5.09375,-7.5 c -0.328125,0 -0.609375,0.296875 -0.609375,0.625 0,0.3125 0.28125,0.59375 0.59375,0.59375 0.328125,0 0.609375,-0.28125 0.609375,-0.59375 0,-0.3125 -0.28125,-0.625 -0.59375,-0.625 z m 0,0"
+ id="path59"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-20"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.25,-4.359375 h 0.40625 c 0.4375,0 0.484375,0.078125 0.484375,0.796875 v 2.453125 c 0,0.6875 -0.046875,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.015625,0.015625 1.296875,0 1.578125,0 1.78125,0 1.78125,0 3.125,0.03125 v -0.328125 l -0.5625,-0.03125 c -0.484375,-0.03125 -0.515625,-0.0625 -0.515625,-0.78125 v -1.875 c 0,-0.65625 0.4375,-1.203125 0.96875,-1.203125 0.328125,0 0.5625,0.15625 0.734375,0.5 H 3.984375 L 4.078125,-5 c -0.125,-0.078125 -0.3125,-0.109375 -0.515625,-0.109375 -0.328125,0 -0.671875,0.171875 -0.90625,0.4375 l -0.609375,0.71875 v -1.125 l -0.09375,-0.03125 c -0.5625,0.21875 -1.125,0.375 -1.703125,0.4375 z m 0,0"
+ id="path62"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-21"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.21875,-1.34375 C 1.9375,-1.25 1.734375,-1.171875 1.15625,-1.015625 1.078125,-0.1875 0.8125,0.53125 0.171875,1.578125 L 0.328125,1.6875 0.78125,1.484375 C 1.65625,0.34375 2.078125,-0.34375 2.375,-1.1875 Z m 0,0"
+ id="path65"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-22"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.640625,-7.828125 1.53125,-7.921875 c -0.46875,0.1875 -0.828125,0.28125 -1.6875,0.40625 v 0.3125 h 0.609375 c 0.1875,0 0.265625,0.109375 0.265625,0.4375 v 5.09375 C 0.71875,-1 0.703125,-0.703125 0.625,0.0625 L 0.8125,0.125 1.25,-0.265625 C 1.671875,0.015625 2.078125,0.125 2.65625,0.125 c 0.421875,0 0.703125,-0.078125 0.9375,-0.234375 l 1.078125,-0.78125 c 0.484375,-0.359375 0.875,-1.265625 0.875,-2.046875 0,-1.265625 -0.828125,-2.171875 -1.984375,-2.171875 -0.515625,0 -1.046875,0.1875 -1.328125,0.46875 l -0.59375,0.609375 z m 0,4.46875 c 0,-0.15625 0.109375,-0.34375 0.28125,-0.546875 0.296875,-0.3125 0.734375,-0.5 1.171875,-0.5 0.921875,0 1.5,0.734375 1.5,1.90625 0,1.21875 -0.65625,2.078125 -1.578125,2.078125 -0.578125,0 -1.375,-0.359375 -1.375,-0.59375 z m 0,0"
+ id="path68"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-23"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.71875,-7.8125 c -0.234375,-0.09375 -0.359375,-0.125 -0.5,-0.125 -0.34375,0 -0.734375,0.1875 -0.96875,0.453125 l -0.640625,0.71875 C 1.296875,-6.40625 1.15625,-5.90625 1.15625,-5.1875 v 0.453125 l -0.75,0.34375 v 0.234375 l 0.75,-0.046875 v 3.09375 c 0,0.6875 -0.03125,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.34375,0 1.34375,0 1.609375,0 c 0.28125,0 0.28125,0 1.375,0.03125 V -0.296875 L 2.46875,-0.328125 C 2.109375,-0.34375 2.078125,-0.421875 2.078125,-1.109375 v -3.09375 h 1.34375 L 3.5,-4.78125 2.078125,-4.734375 V -5.65625 c 0,-1.265625 0.140625,-1.5625 0.75,-1.5625 0.296875,0 0.5,0.078125 0.765625,0.296875 l 0.125,-0.0625 z m 0,0"
+ id="path71"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-24"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.484375,-5.078125 -0.09375,-0.03125 c -0.5625,0.21875 -1.125,0.375 -1.703125,0.4375 v 0.3125 h 0.40625 c 0.4375,0 0.46875,0.078125 0.46875,0.796875 v 1.78125 C 4.5625,-1.546875 4.421875,-1.25 4.171875,-1 c -0.3125,0.3125 -0.65625,0.46875 -1.078125,0.46875 -0.390625,0 -0.6875,-0.125 -0.875,-0.328125 C 2.078125,-1.03125 2,-1.375 2,-1.859375 v -3.21875 l -0.109375,-0.03125 c -0.546875,0.21875 -1.109375,0.375 -1.6875,0.4375 v 0.3125 H 0.59375 c 0.4375,0 0.484375,0.078125 0.484375,0.796875 v 1.828125 c 0,0.765625 0.0625,1.109375 0.265625,1.375 C 1.578125,-0.03125 2,0.125 2.625,0.125 c 0.484375,0 0.921875,-0.140625 1.21875,-0.421875 L 4.5625,-0.96875 c 0,0.3125 0,0.484375 -0.03125,1 C 5.25,0 5.265625,0 5.4375,0 5.578125,0 5.578125,0 6.34375,0.03125 v -0.328125 l -0.453125,-0.03125 c -0.375,-0.015625 -0.40625,-0.09375 -0.40625,-0.78125 z m 0,0"
+ id="path74"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-25"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.28125,-0.71875 V 1.921875 C 4.28125,2.609375 4.25,2.6875 3.875,2.703125 L 3.25,2.734375 V 3.0625 C 4.515625,3.03125 4.515625,3.03125 4.765625,3.03125 c 0.265625,0 0.5625,0.015625 1.34375,0.03125 V 2.734375 l -0.5,-0.03125 C 5.234375,2.6875 5.203125,2.609375 5.203125,1.921875 V -3.46875 c 0,-0.671875 0.0625,-1.09375 0.25,-1.5 L 5.25,-5.09375 4.71875,-4.75 c -0.5625,-0.25 -1.03125,-0.359375 -1.5,-0.359375 -0.3125,0 -0.703125,0.078125 -0.859375,0.1875 L 1.4375,-4.34375 C 0.734375,-3.890625 0.375,-3.171875 0.375,-2.21875 0.375,-0.796875 1.25,0.125 2.59375,0.125 2.828125,0.125 3.015625,0.09375 3.15625,0 Z m 0,-0.59375 c 0,0.15625 -0.25,0.4375 -0.546875,0.609375 -0.265625,0.140625 -0.515625,0.21875 -0.78125,0.21875 -0.953125,0 -1.625,-0.90625 -1.625,-2.21875 0,-1.203125 0.609375,-1.90625 1.65625,-1.90625 0.53125,0 0.921875,0.140625 1.296875,0.453125 z m 0,0"
+ id="path77"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-26"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.96875,-4.71875 v -0.3125 C 4.203125,-5.015625 3.875,-5 3.453125,-5 L 0.75,-5.03125 c -0.015625,0.546875 -0.03125,0.671875 -0.09375,1.4375 h 0.328125 l 0.125,-0.75 C 1.15625,-4.5625 1.359375,-4.625 2.15625,-4.625 h 1.5625 c -0.234375,0.359375 -0.421875,0.609375 -0.703125,0.984375 l -1.859375,2.3125 c -0.265625,0.3125 -0.421875,0.5 -0.984375,1.140625 l 0.0625,0.21875 C 1.375,0 1.4375,0 1.90625,0 l 3.015625,0.03125 c 0,-0.25 0.015625,-0.515625 0.09375,-1.03125 l 0.0625,-0.515625 H 4.75 L 4.5625,-0.65625 C 4.515625,-0.453125 4.0625,-0.375 3.015625,-0.375 H 1.53125 Z m 0,0"
+ id="path80"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-27"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.65625,-4.125 5.9375,-4.5625 5.890625,-4.703125 4.34375,-4.65625 C 3.9375,-4.984375 3.546875,-5.109375 3.015625,-5.109375 c -0.484375,0 -1.046875,0.140625 -1.484375,0.40625 -0.609375,0.34375 -0.9375,0.890625 -0.9375,1.546875 0,0.8125 0.5,1.375 1.3125,1.453125 L 1.046875,-1.03125 C 0.9375,-0.875 0.890625,-0.734375 0.890625,-0.5625 c 0,0.296875 0.1875,0.46875 0.71875,0.625 L 0.65625,0.578125 C 0.5,0.671875 0.34375,1.0625 0.34375,1.40625 c 0,1 0.96875,1.6875 2.359375,1.6875 1.65625,0 2.953125,-1.046875 2.953125,-2.375 0,-0.78125 -0.53125,-1.328125 -1.296875,-1.328125 H 2.625 c -0.578125,0 -0.84375,-0.125 -0.84375,-0.421875 0,-0.140625 0.09375,-0.265625 0.375,-0.5 0.0625,-0.0625 0.09375,-0.078125 0.140625,-0.125 0.109375,0.015625 0.171875,0.015625 0.25,0.015625 0.46875,0 1.046875,-0.203125 1.5,-0.515625 C 4.53125,-2.515625 4.78125,-2.953125 4.78125,-3.53125 4.78125,-3.75 4.75,-3.890625 4.65625,-4.125 Z M 2.625,-4.75 c 0.734375,0 1.234375,0.609375 1.234375,1.546875 C 3.859375,-2.5 3.40625,-2 2.734375,-2 2,-2 1.515625,-2.578125 1.515625,-3.40625 1.515625,-4.25 1.921875,-4.75 2.625,-4.75 Z m 0.5,4.90625 c 1.234375,0 1.65625,0.25 1.65625,0.953125 0,0.9375 -0.859375,1.640625 -2,1.640625 -0.953125,0 -1.609375,-0.5625 -1.609375,-1.359375 0,-0.5 0.296875,-0.9375 0.71875,-1.125 C 2.078125,0.171875 2.375,0.15625 3.125,0.15625 Z m 0,0"
+ id="path83"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-28"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.28125,2.109375 C 2.5,1.140625 2.21875,0.625 1.9375,-0.359375 1.703125,-1.140625 1.59375,-1.96875 1.59375,-2.90625 c 0,-0.90625 0.109375,-1.671875 0.3125,-2.390625 0.28125,-0.890625 0.578125,-1.40625 1.375,-2.34375 l -0.203125,-0.28125 c -1.140625,1.015625 -1.578125,1.625 -2,2.6875 -0.28125,0.734375 -0.421875,1.5 -0.421875,2.328125 0,1.171875 0.265625,2.28125 0.796875,3.25 0.375,0.734375 0.734375,1.15625 1.625,2 z m 0,0"
+ id="path86"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-29"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.046875,-1.96875 v 0.8125 c 0,0.65625 -0.109375,0.8125 -0.640625,0.828125 l -0.6875,0.03125 V 0.03125 C 3.171875,0 3.171875,0 3.4375,0 3.703125,0 3.703125,0 5.140625,0.03125 V -0.296875 L 4.625,-0.328125 C 4.09375,-0.359375 3.96875,-0.5 3.96875,-1.15625 v -0.8125 c 0.640625,0 0.875,0 1.171875,0.03125 v -0.765625 c -0.5,0.046875 -0.71875,0.046875 -0.875,0.03125 H 3.96875 V -4.1875 c 0,-1.9375 0.015625,-2.875 0.078125,-3.328125 l -0.125,-0.046875 -0.8125,0.28125 -3.09375,5.0625 0.125,0.25 z m 0,-0.703125 h -2.34375 l 2.34375,-3.84375 z m 0,0"
+ id="path89"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-30"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.359375,-1.203125 c -0.328125,0 -0.625,0.296875 -0.625,0.625 0,0.328125 0.296875,0.625 0.609375,0.625 0.34375,0 0.65625,-0.28125 0.65625,-0.625 0,-0.328125 -0.3125,-0.625 -0.640625,-0.625 z m 0,0"
+ id="path92"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-31"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.734375,-6.046875 H 0.84375 L 2.25,-6.6875 c 0,-0.015625 0.015625,-0.015625 0.03125,-0.015625 0.0625,0 0.078125,0.109375 0.078125,0.359375 v 5.296875 c 0,0.5625 -0.109375,0.6875 -0.703125,0.71875 l -0.609375,0.03125 V 0.03125 C 2.71875,0 2.71875,0 2.84375,0 c 0.140625,0 0.390625,0 0.75,0.015625 0.140625,0 0.515625,0 0.96875,0.015625 V -0.296875 L 3.984375,-0.328125 C 3.390625,-0.359375 3.28125,-0.484375 3.28125,-1.046875 v -6.46875 L 3.125,-7.5625 C 2.421875,-7.203125 1.640625,-6.875 0.65625,-6.515625 Z m 0,0"
+ id="path95"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-32"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.5625,2.34375 c 0.75,-0.703125 1.0625,-1.0625 1.40625,-1.609375 0.65625,-1.046875 1.015625,-2.3125 1.015625,-3.625 0,-0.84375 -0.15625,-1.609375 -0.4375,-2.34375 -0.40625,-1.0625 -0.859375,-1.65625 -1.984375,-2.6875 l -0.21875,0.28125 c 0.796875,0.9375 1.09375,1.453125 1.375,2.34375 0.21875,0.71875 0.328125,1.484375 0.328125,2.390625 0,0.9375 -0.109375,1.765625 -0.34375,2.546875 -0.28125,0.984375 -0.5625,1.5 -1.359375,2.46875 z m 0,0"
+ id="path98"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-33"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.359375,-6.203125 C 2.359375,-7.0625 2.40625,-7.15625 2.90625,-7.1875 L 3.4375,-7.21875 v -0.328125 c -0.796875,0.03125 -1.03125,0.03125 -1.609375,0.03125 -0.546875,0 -0.796875,-0.015625 -1.59375,-0.03125 v 0.328125 l 0.53125,0.03125 c 0.5,0.03125 0.546875,0.125 0.546875,0.984375 v 5.171875 c 0,0.3125 -0.09375,0.546875 -0.265625,0.640625 l -0.34375,0.171875 v 0.25 C 1.421875,0 1.5,0 1.78125,0 1.890625,0 2.0625,0 2.296875,0.015625 c 0.53125,0 1.734375,0.015625 2.03125,0.015625 0.34375,0 0.34375,0 1.828125,-0.03125 0.078125,-0.46875 0.125,-0.8125 0.234375,-1.875 H 6.046875 L 5.90625,-1.328125 c 0,0.03125 -0.015625,0.109375 -0.03125,0.125 -0.0625,0.3125 -0.140625,0.53125 -0.203125,0.578125 -0.140625,0.125 -1.09375,0.203125 -2.390625,0.203125 -0.390625,0 -0.640625,-0.03125 -0.921875,-0.09375 z m 0,0"
+ id="path101"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-34"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.25,-7.203125 h 0.609375 c 0.203125,0 0.28125,0.109375 0.28125,0.4375 v 5.65625 c 0,0.6875 -0.046875,0.765625 -0.40625,0.78125 l -0.5,0.03125 V 0.03125 C 1.3125,0 1.3125,0 1.609375,0 1.90625,0 1.96875,0 2.9375,0.03125 v -0.328125 l -0.484375,-0.03125 c -0.375,-0.015625 -0.40625,-0.09375 -0.40625,-0.78125 V -2.625 L 4.9375,0.125 5.984375,-0.1875 v -0.25 C 5.71875,-0.4375 5.40625,-0.625 5.0625,-0.953125 l -1.375,-1.375 C 3.296875,-2.703125 3.171875,-2.84375 2.984375,-3.0625 l 1.40625,-1.109375 c 0.515625,-0.390625 0.8125,-0.515625 1.1875,-0.5 V -5 H 4.484375 C 3.78125,-4.3125 3.265625,-3.828125 2.84375,-3.484375 L 2.046875,-2.84375 v -4.984375 l -0.09375,-0.09375 c -0.484375,0.1875 -0.84375,0.28125 -1.703125,0.40625 z m 0,0"
+ id="path104"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-35"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.5,-5.109375 C 3.609375,-3.03125 3.453125,-2.65625 2.765625,-1.140625 l -0.90625,-3 C 1.828125,-4.25 1.8125,-4.328125 1.8125,-4.421875 c 0,-0.15625 0.140625,-0.25 0.40625,-0.25 l 0.4375,-0.03125 V -5 c -1.078125,0.03125 -1.078125,0.03125 -1.296875,0.03125 -0.21875,0 -0.21875,0 -1.296875,-0.03125 v 0.296875 l 0.3125,0.03125 C 0.671875,-4.65625 0.8125,-4.4375 1.09375,-3.59375 L 2.203125,0.078125 H 2.71875 L 3.78125,-2.4375 c 0.0625,-0.125 0.171875,-0.390625 0.359375,-0.765625 l 0.21875,-0.453125 1.46875,3.734375 H 6.34375 C 6.40625,-0.15625 6.5,-0.40625 6.59375,-0.640625 6.8125,-1.28125 7.046875,-1.96875 7.09375,-2.03125 l 0.734375,-1.703125 c 0.328125,-0.71875 0.453125,-0.90625 0.703125,-0.9375 L 8.8125,-4.703125 V -5 c -0.890625,0.03125 -0.890625,0.03125 -1.0625,0.03125 -0.1875,0 -0.1875,0 -1.078125,-0.03125 v 0.296875 l 0.375,0.03125 c 0.265625,0 0.421875,0.140625 0.421875,0.328125 0,0.125 -0.015625,0.25 -0.078125,0.390625 L 6.84375,-2.421875 C 6.765625,-2.1875 6.671875,-1.96875 6.328125,-1.0625 l -1.25,-3.171875 c -0.15625,-0.375 -0.234375,-0.59375 -0.328125,-0.875 z m 0,0"
+ id="path107"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-36"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.078125,-2.34375 3.40625,-3.078125 3.34375,-3.125 H 0.484375 l -0.296875,0.71875 0.046875,0.0625 z m 0,0"
+ id="path110"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-37"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.5,-7.515625 C 0.890625,-7.53125 0.78125,-7.53125 0.1875,-7.546875 v 0.328125 l 0.484375,0.03125 c 0.5,0.03125 0.546875,0.125 0.546875,0.984375 V -1.3125 c 0,0.859375 -0.046875,0.953125 -0.546875,0.984375 L 0.1875,-0.296875 V 0.03125 C 1.265625,0 1.265625,0 1.453125,0 c 0.15625,0 0.15625,0 1.3125,0.03125 V -0.296875 L 2.28125,-0.328125 c -0.5,-0.03125 -0.5625,-0.125 -0.5625,-0.984375 V -6.359375 L 6.875,0.046875 7.859375,0.21875 c 0,-0.046875 0,-0.0625 0,-0.125 C 7.84375,-0.03125 7.828125,-0.125 7.828125,-0.1875 v -6.015625 c 0,-0.859375 0.0625,-0.953125 0.5625,-0.984375 l 0.46875,-0.03125 v -0.328125 c -1.140625,0.03125 -1.140625,0.03125 -1.296875,0.03125 -0.1875,0 -0.1875,0 -1.265625,-0.03125 v 0.328125 l 0.46875,0.03125 c 0.515625,0.03125 0.5625,0.125 0.5625,0.984375 V -1.0625 l -5.25,-6.484375 z m 0,0"
+ id="path113"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-38"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 2.875,-7.515625 c -1.703125,0 -2.5625,1.34375 -2.5625,3.984375 0,1.28125 0.234375,2.375 0.609375,2.90625 0.390625,0.53125 1,0.84375 1.671875,0.84375 1.65625,0 2.484375,-1.421875 2.484375,-4.203125 0,-2.390625 -0.71875,-3.53125 -2.203125,-3.53125 z M 2.671875,-7.125 c 1.0625,0 1.484375,1.0625 1.484375,3.671875 0,2.328125 -0.421875,3.296875 -1.421875,3.296875 -1.0625,0 -1.5,-1.109375 -1.5,-3.765625 0,-2.3125 0.40625,-3.203125 1.4375,-3.203125 z m 0,0"
+ id="path116"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-39"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.359375,-6.203125 C 2.359375,-7.0625 2.40625,-7.15625 2.90625,-7.1875 L 3.4375,-7.21875 v -0.328125 c -0.796875,0.03125 -1.03125,0.03125 -1.609375,0.03125 -0.546875,0 -0.796875,-0.015625 -1.59375,-0.03125 v 0.328125 l 0.53125,0.03125 c 0.5,0.03125 0.546875,0.125 0.546875,0.984375 V -1.3125 c 0,0.859375 -0.046875,0.953125 -0.546875,0.984375 l -0.53125,0.03125 V 0.03125 C 0.890625,0.015625 1.265625,0 1.828125,0 2.40625,0 2.796875,0.015625 3.4375,0.03125 v -0.328125 l -0.53125,-0.03125 c -0.5,-0.03125 -0.546875,-0.125 -0.546875,-0.984375 z m 0,0"
+ id="path119"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-40"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.34375,-1.203125 c -0.328125,0 -0.625,0.296875 -0.625,0.625 0,0.328125 0.296875,0.625 0.609375,0.625 0.34375,0 0.65625,-0.28125 0.65625,-0.625 0,-0.328125 -0.3125,-0.625 -0.640625,-0.625 z m 0,-3.765625 c -0.328125,0 -0.625,0.296875 -0.625,0.625 0,0.328125 0.296875,0.640625 0.609375,0.640625 0.34375,0 0.65625,-0.296875 0.65625,-0.625 0,-0.34375 -0.3125,-0.640625 -0.640625,-0.640625 z m 0,0"
+ id="path122"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-41"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.390625,-6.59375 c 1.40625,0.046875 2.015625,0.046875 3.328125,0.046875 L 4.765625,-6.59375 C 4.75,-6.796875 4.75,-6.875 4.75,-7.03125 c 0,-0.140625 0,-0.234375 0.015625,-0.421875 l -0.046875,-0.0625 c -0.828125,0.046875 -1.3125,0.0625 -1.90625,0.0625 -0.59375,0 -1.078125,-0.015625 -1.890625,-0.0625 l -0.0625,0.0625 c 0.015625,0.65625 0.03125,1.140625 0.03125,1.484375 0,0.9375 -0.046875,1.984375 -0.078125,2.453125 l 0.21875,0.0625 c 0.515625,-0.5 0.8125,-0.65625 1.34375,-0.65625 1.046875,0 1.703125,0.734375 1.703125,1.921875 0,1.203125 -0.703125,1.921875 -1.890625,1.921875 -0.578125,0 -1.125,-0.203125 -1.28125,-0.484375 l -0.5,-0.890625 L 0.140625,-1.5 c 0.25,0.625 0.390625,0.96875 0.53125,1.453125 0.3125,0.171875 0.75,0.265625 1.21875,0.265625 0.734375,0 1.5,-0.3125 2.09375,-0.84375 C 4.65625,-1.203125 5,-1.953125 5,-2.765625 c 0,-1.21875 -0.875,-2.09375 -2.125,-2.09375 -0.515625,0 -0.90625,0.140625 -1.59375,0.546875 z m 0,0"
+ id="path125"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-42"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.53125,-7.328125 -0.390625,-0.1875 c -1.046875,0.34375 -1.5,0.5625 -2.0625,1.046875 -1.125,0.953125 -1.734375,2.28125 -1.734375,3.78125 0,1.796875 0.875,2.90625 2.28125,2.90625 1.421875,0 2.484375,-1.125 2.484375,-2.609375 0,-1.25 -0.75,-2.0625 -1.90625,-2.0625 -0.546875,0 -0.875,0.140625 -1.53125,0.640625 -0.109375,0.109375 -0.125,0.109375 -0.25,0.203125 0.234375,-1.96875 1.15625,-3.046875 3.109375,-3.625 z m -1.75,3.515625 c 0.828125,0 1.390625,0.71875 1.390625,1.8125 0,1.125 -0.5625,1.859375 -1.40625,1.859375 -0.921875,0 -1.421875,-0.796875 -1.421875,-2.265625 0,-0.375 0.046875,-0.578125 0.15625,-0.765625 0.25,-0.375 0.75,-0.640625 1.28125,-0.640625 z m 0,0"
+ id="path128"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-43"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.140625,-2.765625 1.546875,-1.8125 c 0.0625,-0.078125 0.1875,-0.125 0.375,-0.125 H 5.21875 V -5 H 4.3125 L 2.96875,-3.09375 2.140625,-4.359375 c -0.171875,-0.25 -0.28125,-0.390625 -0.65625,-0.75 L 0.21875,-4.890625 0.265625,-4.609375 0.5,-4.59375 c 0.203125,0.015625 0.4375,0.171875 0.546875,0.3125 l 1.3125,1.90625 -1.625,1.921875 c -0.078125,0.09375 -0.21875,0.15625 -0.328125,0.15625 H 0.21875 V 0 h 0.9375 C 1.234375,-0.125 1.25,-0.15625 1.390625,-0.359375 1.5625,-0.671875 1.734375,-0.9375 1.8125,-1.03125 l 0.8125,-1.0625 1.15625,1.765625 0.015625,0.015625 c 0.09375,0.15625 0.1875,0.265625 0.265625,0.34375 C 4.640625,0 4.640625,0 4.734375,0 4.84375,0 4.84375,0 5.40625,0.03125 V -0.296875 L 5.140625,-0.328125 C 5,-0.34375 4.875,-0.421875 4.75,-0.59375 Z m 0,0"
+ id="path131"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-44"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 2.359375,-3.5625 c 0.296875,-0.03125 0.625,-0.03125 1.125,-0.03125 0.796875,0 1.09375,0.03125 1.296875,0.125 l 0.078125,0.265625 0.0625,0.65625 H 5.25 C 5.21875,-3.5625 5.21875,-3.5625 5.21875,-3.765625 c 0,-0.171875 0,-0.171875 0.03125,-1.265625 H 4.921875 l -0.0625,0.578125 c 0,0.09375 -0.03125,0.1875 -0.078125,0.28125 -0.203125,0.078125 -0.5,0.109375 -1.21875,0.109375 -0.46875,0 -0.84375,0 -1.203125,-0.03125 V -7 C 2.6875,-7.078125 2.875,-7.09375 3.515625,-7.09375 c 0.53125,0 1.140625,0.0625 1.484375,0.15625 0.25,0.0625 0.296875,0.125 0.296875,0.375 v 0.703125 h 0.375 c 0,-0.65625 0.046875,-1.171875 0.171875,-1.65625 C 5.3125,-7.53125 4.984375,-7.546875 4.515625,-7.546875 L 3.34375,-7.53125 c -0.53125,0.015625 -0.90625,0.015625 -1.1875,0.015625 -0.3125,0 -0.3125,0 -1.921875,-0.03125 v 0.328125 l 0.53125,0.03125 c 0.5,0.03125 0.546875,0.125 0.546875,0.984375 V -1.3125 c 0,0.859375 -0.046875,0.953125 -0.546875,0.984375 l -0.53125,0.03125 V 0.03125 C 0.890625,0.015625 1.265625,0 1.828125,0 2.40625,0 2.796875,0.015625 3.4375,0.03125 v -0.328125 l -0.53125,-0.03125 c -0.5,-0.03125 -0.546875,-0.125 -0.546875,-0.984375 z m 0,0"
+ id="path134"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph0-45"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.828125,-3.765625 c -0.4375,0.203125 -0.625,0.328125 -0.875,0.5625 -0.40625,0.40625 -0.625,0.90625 -0.625,1.46875 0,1.125 0.90625,1.953125 2.140625,1.953125 1.40625,0 2.59375,-1.109375 2.59375,-2.46875 0,-0.875 -0.40625,-1.34375 -1.65625,-1.90625 1,-0.671875 1.34375,-1.140625 1.34375,-1.78125 0,-0.9375 -0.765625,-1.578125 -1.921875,-1.578125 -1.296875,0 -2.25,0.828125 -2.25,1.96875 0,0.75 0.296875,1.15625 1.25,1.78125 z M 3.09375,-3.21875 c 0.6875,0.3125 1.109375,0.84375 1.109375,1.4375 0,0.90625 -0.6875,1.625 -1.578125,1.625 -0.921875,0 -1.53125,-0.65625 -1.53125,-1.671875 0,-0.796875 0.328125,-1.296875 1.125,-1.78125 z M 2.4375,-4.609375 C 1.75,-4.953125 1.390625,-5.390625 1.390625,-5.9375 c 0,-0.71875 0.53125,-1.203125 1.296875,-1.203125 0.796875,0 1.328125,0.515625 1.328125,1.3125 0,0.625 -0.28125,1.046875 -0.984375,1.515625 z m 0,0"
+ id="path137"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path140"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 7.453125,-0.921875 7.390625,-1.03125 C 6.625,-0.59375 5.84375,-0.375 5.015625,-0.375 c -2.125,0 -3.3125,-1.40625 -2.953125,-3.5625 0.34375,-2 1.796875,-3.34375 3.671875,-3.34375 1.078125,0 2.109375,0.4375 2.03125,0.875 l -0.125,0.78125 H 7.96875 c 0.109375,-0.546875 0.21875,-0.9375 0.5,-1.65625 C 7.578125,-7.59375 6.8125,-7.734375 6.015625,-7.734375 5.0625,-7.734375 4.125,-7.5 3.3125,-7.078125 1.953125,-6.34375 1.109375,-5.203125 0.859375,-3.734375 0.46875,-1.375 1.9375,0.21875 4.5,0.21875 c 0.90625,0 1.75,-0.203125 2.5625,-0.59375 z m 0,0"
+ id="path143"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 6.9375,-1.3125 C 6.796875,-0.453125 6.734375,-0.359375 6.21875,-0.328125 L 5.6875,-0.296875 5.625,0.03125 C 6.28125,0.015625 6.65625,0 7.234375,0 7.796875,0 8.1875,0.015625 8.828125,0.03125 l 0.0625,-0.328125 -0.53125,-0.03125 C 7.875,-0.359375 7.828125,-0.453125 7.96875,-1.3125 L 8.796875,-6.203125 C 8.9375,-7.0625 9.015625,-7.15625 9.515625,-7.1875 l 0.53125,-0.03125 0.04687,-0.328125 c -0.796875,0.03125 -1.046875,0.03125 -1.609375,0.03125 -0.546875,0 -0.8125,-0.015625 -1.578125,-0.03125 l -0.0625,0.328125 0.515625,0.03125 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 l -0.328125,1.9375 C 7.203125,-4.25 6.96875,-4.25 6.515625,-4.25 H 3.96875 c -0.453125,0 -0.6875,0 -0.90625,-0.015625 l 0.328125,-1.9375 C 3.53125,-7.0625 3.609375,-7.15625 4.109375,-7.1875 l 0.53125,-0.03125 0.0625,-0.328125 c -0.8125,0.03125 -1.046875,0.03125 -1.609375,0.03125 -0.546875,0 -0.8125,-0.015625 -1.59375,-0.03125 L 1.453125,-7.21875 1.96875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.53125,-1.3125 C 1.390625,-0.453125 1.328125,-0.359375 0.8125,-0.328125 l -0.515625,0.03125 -0.0625,0.328125 C 0.890625,0.015625 1.265625,0 1.828125,0 2.40625,0 2.796875,0.015625 3.421875,0.03125 l 0.0625,-0.328125 -0.515625,-0.03125 c -0.5,-0.03125 -0.53125,-0.125 -0.390625,-0.984375 l 0.40625,-2.421875 c 0.296875,-0.03125 0.46875,-0.03125 0.90625,-0.03125 h 2.5625 c 0.421875,0 0.609375,0 0.890625,0.03125 z m 0,0"
+ id="path146"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.71875,-7.640625 H 5.375 c -0.265625,0.46875 -0.5,0.875 -0.59375,1.046875 l -0.796875,1.3125 -2.6875,4.421875 c -0.1875,0.3125 -0.4375,0.515625 -0.671875,0.53125 L 0.21875,-0.296875 0.15625,0.03125 C 1.171875,0 1.171875,0 1.359375,0 1.5,0 1.5,0 2.65625,0.03125 l 0.0625,-0.328125 -0.390625,-0.03125 c -0.375,-0.03125 -0.5,-0.109375 -0.484375,-0.28125 C 1.875,-0.75 2.109375,-1.21875 2.421875,-1.765625 L 2.84375,-2.5 h 3.140625 l 0.296875,1.25 c 0.109375,0.46875 0.125,0.609375 0.109375,0.703125 C 6.375,-0.421875 6.1875,-0.34375 5.90625,-0.328125 l -0.5,0.03125 L 5.328125,0.03125 C 6.6875,0 6.6875,0 6.859375,0 7.0625,0 7.0625,0 8.234375,0.03125 l 0.0625,-0.328125 -0.375,-0.03125 C 7.65625,-0.375 7.5625,-0.5625 7.328125,-1.4375 Z m -2.609375,4.703125 1.921875,-3.25 0.84375,3.25 z m 0,0"
+ id="path149"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.515625,-7 c 0.40625,-0.09375 0.734375,-0.125 1.09375,-0.125 1.1875,0 1.734375,0.53125 1.546875,1.578125 C 6,-4.5625 5.21875,-3.875 4.265625,-3.875 4.03125,-3.875 3.875,-3.90625 3.609375,-3.984375 L 3.65625,-3.59375 c 0.25,0.046875 0.40625,0.0625 0.625,0.0625 1.484375,0 2.8125,-1.015625 3.03125,-2.328125 0.171875,-1.046875 -0.578125,-1.6875 -1.953125,-1.6875 -0.0625,0 -0.171875,0 -0.328125,0.015625 -0.390625,0 -1.21875,0.015625 -1.546875,0.015625 -0.234375,0 -0.234375,0 -1.96875,-0.03125 L 1.46875,-7.21875 1.9375,-7.1875 c 0.5,0.03125 0.546875,0.171875 0.421875,0.984375 L 1.53125,-1.3125 C 1.390625,-0.453125 1.328125,-0.359375 0.8125,-0.328125 l -0.515625,0.03125 -0.0625,0.328125 C 0.890625,0.015625 1.265625,0 1.828125,0 2.40625,0 2.796875,0.015625 3.421875,0.03125 l 0.0625,-0.328125 -0.515625,-0.03125 c -0.5,-0.03125 -0.53125,-0.125 -0.390625,-0.984375 z m 0,0"
+ id="path152"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.953125,-7.015625 c -0.03125,0.375 -0.0625,0.625 -0.140625,1.09375 L 3.046875,-1.3125 c -0.140625,0.859375 -0.21875,0.953125 -0.71875,0.984375 l -0.53125,0.03125 -0.0625,0.328125 C 2.390625,0.015625 2.765625,0 3.34375,0 3.90625,0 4.296875,0.015625 4.921875,0.03125 L 5,-0.296875 4.46875,-0.328125 C 3.984375,-0.359375 3.9375,-0.453125 4.078125,-1.3125 l 0.78125,-4.609375 c 0.0625,-0.484375 0.125,-0.734375 0.21875,-1.09375 h 1.6875 c 0.296875,0 0.40625,0.09375 0.375,0.359375 l -0.09375,0.859375 h 0.34375 C 7.5,-6.5 7.59375,-6.921875 7.75,-7.546875 6.953125,-7.53125 6.59375,-7.53125 6.296875,-7.53125 5.875,-7.515625 5.546875,-7.515625 5.390625,-7.515625 H 3.671875 C 3.5625,-7.515625 2.96875,-7.53125 2.1875,-7.53125 L 1.46875,-7.546875 c -0.0625,0.625 -0.109375,1.046875 -0.21875,1.75 h 0.328125 l 0.1875,-0.859375 c 0.0625,-0.265625 0.1875,-0.359375 0.484375,-0.359375 z m 0,0"
+ id="path155"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.453125,-7.21875 1.96875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.53125,-1.3125 C 1.390625,-0.453125 1.34375,-0.375 0.8125,-0.328125 l -0.390625,0.03125 -0.0625,0.328125 C 1.09375,0.015625 1.40625,0 1.71875,0 c 0.046875,0 0.359375,0 0.765625,0.015625 1.5,0.015625 1.5,0.015625 1.75,0.015625 0.328125,0 0.328125,0 1.828125,-0.03125 0.109375,-0.625 0.28125,-1.21875 0.46875,-1.78125 h -0.375 c -0.046875,0.171875 -0.109375,0.3125 -0.109375,0.359375 -0.140625,0.46875 -0.359375,0.8125 -0.5,0.859375 -0.25,0.078125 -1.046875,0.140625 -2.03125,0.140625 -0.578125,0 -0.765625,-0.03125 -1.078125,-0.09375 L 2.953125,-3.5625 c 0.3125,-0.03125 0.640625,-0.03125 1.125,-0.03125 0.8125,0 1.109375,0.03125 1.28125,0.125 l 0.046875,0.265625 -0.0625,0.65625 H 5.671875 C 5.8125,-3.5625 5.8125,-3.5625 5.84375,-3.765625 5.875,-3.9375 5.875,-3.9375 6.078125,-5.03125 h -0.3125 l -0.15625,0.578125 c -0.03125,0.09375 -0.078125,0.1875 -0.140625,0.28125 C 5.265625,-4.09375 4.953125,-4.0625 4.234375,-4.0625 c -0.453125,0 -0.828125,0 -1.1875,-0.03125 L 3.515625,-7 C 3.875,-7.078125 4.0625,-7.09375 4.828125,-7.09375 c 0.609375,0 1.21875,0.0625 1.546875,0.15625 0.25,0.0625 0.265625,0.125 0.234375,0.375 l -0.125,0.703125 H 6.875 c 0.109375,-0.65625 0.25,-1.171875 0.4375,-1.65625 -0.53125,-0.015625 -0.859375,-0.03125 -1.328125,-0.03125 -0.28125,0 -0.640625,0 -1.09375,0.015625 -0.6875,0 -1.15625,0.015625 -1.453125,0.015625 -0.375,0 -0.859375,-0.015625 -1.9375,-0.03125 z m 0,0"
+ id="path158"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.515625,-7 c 0.40625,-0.09375 0.734375,-0.125 1.09375,-0.125 1.140625,0 1.6875,0.515625 1.53125,1.4375 -0.15625,1.015625 -1.0625,1.640625 -2.328125,1.640625 -0.078125,0 -0.1875,0 -0.328125,-0.015625 L 3.40625,-3.921875 C 3.5,-3.78125 3.515625,-3.734375 3.625,-3.59375 3.75,-3.421875 3.78125,-3.375 3.859375,-3.25 l 1.5625,2.6875 c 0.046875,0.09375 0.09375,0.1875 0.15625,0.25 C 5.625,-0.203125 5.6875,-0.109375 5.765625,0.03125 6.28125,0 6.390625,0 6.515625,0 6.609375,0 6.609375,0 7.28125,0.03125 l 0.0625,-0.328125 C 7,-0.328125 6.84375,-0.390625 6.734375,-0.578125 L 4.78125,-3.8125 C 5.4375,-3.953125 5.71875,-4.078125 6.125,-4.328125 6.765625,-4.734375 7.171875,-5.28125 7.28125,-5.90625 7.453125,-6.953125 6.78125,-7.546875 5.4375,-7.546875 H 5.25 c -1.421875,0.03125 -1.421875,0.03125 -1.796875,0.03125 -0.359375,0 -0.359375,0 -1.875,-0.03125 L 1.53125,-7.21875 1.96875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.53125,-1.3125 C 1.390625,-0.453125 1.328125,-0.359375 0.8125,-0.328125 l -0.515625,0.03125 -0.0625,0.328125 C 0.890625,0.015625 1.265625,0 1.828125,0 2.40625,0 2.796875,0.015625 3.421875,0.03125 l 0.0625,-0.328125 -0.515625,-0.03125 c -0.5,-0.03125 -0.53125,-0.125 -0.390625,-0.984375 z m 0,0"
+ id="path161"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-8"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.375,-1.96875 3.25,-1.15625 C 3.140625,-0.5 2.984375,-0.34375 2.453125,-0.328125 L 1.78125,-0.296875 1.71875,0.03125 C 3.171875,0 3.171875,0 3.4375,0 3.703125,0 3.703125,0 5.140625,0.03125 l 0.0625,-0.328125 -0.53125,-0.03125 C 4.15625,-0.359375 4.0625,-0.5 4.171875,-1.15625 l 0.125,-0.8125 c 0.640625,0 0.875,0 1.171875,0.03125 l 0.125,-0.765625 C 5.078125,-2.65625 4.875,-2.65625 4.71875,-2.671875 H 4.421875 l 0.25,-1.515625 c 0.328125,-1.9375 0.5,-2.875 0.625,-3.328125 L 5.1875,-7.5625 l -0.875,0.28125 -3.921875,5.0625 0.078125,0.25 z M 3.5,-2.671875 H 1.15625 l 2.984375,-3.84375 z m 0,0"
+ id="path164"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-9"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.5625,-1.203125 c -0.328125,0 -0.671875,0.296875 -0.734375,0.625 -0.046875,0.328125 0.1875,0.625 0.5,0.625 0.34375,0 0.71875,-0.28125 0.765625,-0.625 0.0625,-0.328125 -0.203125,-0.625 -0.53125,-0.625 z m 0,0"
+ id="path167"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-10"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.828125,-5.734375 C 5.9375,-6.3125 6.03125,-6.6875 6.234375,-7.28125 5.4375,-7.625 4.953125,-7.734375 4.359375,-7.734375 c -1.640625,0 -2.96875,1.03125 -3.21875,2.453125 -0.078125,0.53125 0,0.921875 0.25,1.21875 0.328125,0.34375 0.796875,0.515625 1.828125,0.65625 0.8125,0.125 1.171875,0.25 1.421875,0.5 0.25,0.21875 0.328125,0.546875 0.25,0.953125 -0.15625,0.984375 -1.09375,1.6875 -2.234375,1.6875 -0.875,0 -1.640625,-0.421875 -1.625,-0.875 L 1.0625,-1.859375 H 0.71875 c -0.015625,0.1875 -0.046875,0.359375 -0.0625,0.4375 -0.09375,0.5 -0.140625,0.734375 -0.296875,1.21875 0.578125,0.28125 1.1875,0.421875 1.828125,0.421875 1.890625,0 3.453125,-1.140625 3.71875,-2.734375 0.078125,-0.5 0,-0.859375 -0.25,-1.15625 -0.328125,-0.359375 -0.765625,-0.5 -1.953125,-0.65625 C 2.40625,-4.5 1.984375,-4.859375 2.125,-5.703125 2.28125,-6.625 3.078125,-7.28125 4.03125,-7.28125 c 0.421875,0 0.828125,0.09375 1.09375,0.25 0.328125,0.1875 0.421875,0.359375 0.390625,0.671875 l -0.03125,0.625 z m 0,0"
+ id="path170"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-11"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.671875,-7.734375 c -2.484375,0 -4.40625,1.609375 -4.8125,4.015625 C 0.484375,-1.421875 1.796875,0.21875 4,0.21875 6.453125,0.21875 8.609375,-1.609375 9,-4 9.375,-6.296875 8.09375,-7.734375 5.671875,-7.734375 Z M 5.40625,-7.28125 c 1.875,0 2.75,1.34375 2.375,3.609375 -0.359375,2.15625 -1.578125,3.4375 -3.265625,3.4375 -1.828125,0 -2.8125,-1.546875 -2.421875,-3.890625 0.34375,-2.015625 1.53125,-3.15625 3.3125,-3.15625 z m 0,0"
+ id="path173"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-12"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.390625,-6.203125 C 3.53125,-7.0625 3.609375,-7.15625 4.109375,-7.1875 l 0.53125,-0.03125 0.0625,-0.328125 c -0.8125,0.03125 -1.046875,0.03125 -1.609375,0.03125 -0.546875,0 -0.8125,-0.015625 -1.59375,-0.03125 L 1.453125,-7.21875 1.96875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.5,-1.03125 c -0.0625,0.3125 -0.203125,0.546875 -0.390625,0.640625 l -0.375,0.171875 -0.03125,0.25 C 1.421875,0 1.5,0 1.78125,0 1.890625,0 2.0625,0 2.296875,0.015625 c 0.53125,0 1.71875,0.015625 2.015625,0.015625 0.359375,0 0.359375,0 1.84375,-0.03125 0.15625,-0.46875 0.265625,-0.8125 0.546875,-1.875 H 6.359375 L 6.125,-1.328125 c 0,0.03125 -0.03125,0.109375 -0.046875,0.125 -0.109375,0.3125 -0.234375,0.53125 -0.296875,0.578125 -0.171875,0.125 -1.125,0.203125 -2.421875,0.203125 -0.390625,0 -0.640625,-0.03125 -0.921875,-0.09375 z m 0,0"
+ id="path176"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-13"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.390625,-6.203125 C 3.53125,-7.0625 3.609375,-7.15625 4.109375,-7.1875 l 0.53125,-0.03125 0.0625,-0.328125 c -0.8125,0.03125 -1.046875,0.03125 -1.609375,0.03125 -0.546875,0 -0.8125,-0.015625 -1.59375,-0.03125 L 1.453125,-7.21875 1.96875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.53125,-1.3125 C 1.390625,-0.453125 1.328125,-0.359375 0.8125,-0.328125 l -0.515625,0.03125 -0.0625,0.328125 C 0.890625,0.015625 1.265625,0 1.828125,0 2.40625,0 2.796875,0.015625 3.421875,0.03125 l 0.0625,-0.328125 -0.515625,-0.03125 c -0.5,-0.03125 -0.53125,-0.125 -0.390625,-0.984375 z m 0,0"
+ id="path179"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-14"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.65625,-0.21875 -0.046875,0.25 C 1.890625,0 1.890625,0 2.140625,0 c 0.1875,0 0.375,0 0.5625,0.015625 0.859375,0.015625 0.859375,0.015625 1,0.015625 1.40625,0 2.515625,-0.359375 3.40625,-1.109375 0.90625,-0.78125 1.578125,-1.953125 1.78125,-3.125 0.34375,-2.03125 -0.9375,-3.34375 -3.234375,-3.34375 -0.078125,0 -0.21875,0 -0.4375,0.015625 -0.546875,0 -1.015625,0.015625 -1.484375,0.015625 -0.390625,0 -1,-0.015625 -2.234375,-0.03125 L 1.453125,-7.21875 1.875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.40625,-1.03125 c -0.046875,0.3125 -0.203125,0.546875 -0.375,0.640625 z m 2.796875,-6.8125 c 0.28125,-0.046875 0.671875,-0.078125 1.21875,-0.078125 0.796875,0 1.640625,0.140625 2.0625,0.34375 0.21875,0.109375 0.40625,0.25 0.578125,0.453125 C 7.75,-5.796875 7.859375,-5 7.671875,-3.921875 7.46875,-2.6875 6.953125,-1.75 6.125,-1.171875 5.390625,-0.625 4.703125,-0.453125 3.46875,-0.453125 c -0.5,0 -0.84375,-0.015625 -1.109375,-0.078125 z m 0,0"
+ id="path182"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-15"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 8.203125,-1.3125 C 8.0625,-0.453125 8,-0.375 7.484375,-0.328125 l -0.375,0.03125 -0.0625,0.328125 C 7.5625,0.015625 7.890625,0 8.453125,0 c 0.609375,0 1,0.015625 1.640625,0.03125 L 10.15625,-0.296875 9.625,-0.328125 C 9.140625,-0.359375 9.09375,-0.453125 9.234375,-1.3125 L 10.0625,-6.203125 C 10.203125,-7.0625 10.28125,-7.15625 10.78125,-7.1875 l 0.46875,-0.03125 0.04687,-0.328125 c -0.84375,0.03125 -0.84375,0.03125 -1.015625,0.03125 -0.171875,0 -0.171875,0 -1.03125,-0.03125 l -3.875,6.0625 -1.859375,-6.0625 C 2.625,-7.515625 2.625,-7.515625 2.46875,-7.515625 c -0.171875,0 -0.171875,0 -1.03125,-0.03125 l -0.046875,0.328125 0.46875,0.03125 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 1.421875,-1.3125 C 1.28125,-0.453125 1.21875,-0.359375 0.703125,-0.328125 L 0.234375,-0.296875 0.15625,0.03125 C 1.25,0 1.25,0 1.4375,0 1.609375,0 1.609375,0 2.734375,0.03125 l 0.0625,-0.328125 -0.46875,-0.03125 c -0.5,-0.03125 -0.546875,-0.125 -0.390625,-0.984375 l 0.828125,-4.984375 1.96875,6.4375 h 0.21875 c 0.09375,-0.15625 0.1875,-0.34375 0.296875,-0.5 C 5.484375,-0.78125 5.671875,-1.09375 5.765625,-1.25 l 2.625,-4.109375 C 8.609375,-5.6875 8.78125,-5.9375 9.046875,-6.296875 Z m 0,0"
+ id="path185"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph1-16"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.75,-7.515625 C 2.140625,-7.53125 2.046875,-7.53125 1.453125,-7.546875 l -0.0625,0.328125 0.46875,0.03125 c 0.5,0.03125 0.546875,0.125 0.390625,0.984375 L 1.4375,-1.3125 c -0.140625,0.859375 -0.203125,0.953125 -0.71875,0.984375 l -0.484375,0.03125 -0.0625,0.328125 C 1.265625,0 1.265625,0 1.453125,0 1.609375,0 1.609375,0 2.75,0.03125 L 2.8125,-0.296875 2.328125,-0.328125 C 1.84375,-0.359375 1.796875,-0.453125 1.9375,-1.3125 L 2.78125,-6.359375 6.875,0.046875 7.828125,0.21875 c 0,-0.046875 0,-0.0625 0.015625,-0.125 0.015625,-0.125 0.015625,-0.21875 0.015625,-0.28125 l 1,-6.015625 C 9.015625,-7.0625 9.078125,-7.15625 9.59375,-7.1875 l 0.484375,-0.03125 0.04687,-0.328125 c -1.15625,0.03125 -1.15625,0.03125 -1.3125,0.03125 -0.1875,0 -0.1875,0 -1.25,-0.03125 L 7.5,-7.21875 7.96875,-7.1875 c 0.5,0.03125 0.53125,0.125 0.390625,0.984375 L 7.5,-1.0625 3.34375,-7.546875 Z m 0,0"
+ id="path188"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path191"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.8125,-0.1875 v -1.015625 c -0.609375,0.21875 -1.03125,0.34375 -1.4375,0.34375 -0.984375,0 -1.765625,-0.625 -1.765625,-1.609375 0,-0.921875 0.609375,-1.625 1.53125,-1.625 0.21875,0 0.421875,0.03125 0.640625,0.09375 v 0.453125 H 4.734375 V -4.75 C 4.15625,-4.921875 3.671875,-5.015625 3.15625,-5.015625 c -1.53125,0 -2.734375,0.96875 -2.734375,2.578125 0,1.640625 1.25,2.53125 2.765625,2.53125 0.515625,0 1.03125,-0.09375 1.625,-0.28125 z m 0,0"
+ id="path194"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.921875,-2.453125 C 4.921875,-3.875 4.171875,-5 2.609375,-5 c -1.546875,0 -2.3125,1.125 -2.3125,2.546875 0,1.421875 0.765625,2.546875 2.3125,2.546875 1.5625,0 2.3125,-1.125 2.3125,-2.546875 z m -1.171875,0 C 3.75,-1.625 3.453125,-0.8125 2.609375,-0.8125 c -0.828125,0 -1.125,-0.828125 -1.125,-1.640625 0,-0.8125 0.296875,-1.625 1.125,-1.625 0.84375,0 1.140625,0.796875 1.140625,1.625 z m 0,0"
+ id="path197"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.28125,0 V -0.921875 H 4.578125 v -2.375 C 4.578125,-4.234375 4.21875,-5 3.109375,-5 c -0.59375,0 -1,0.25 -1.3125,0.640625 v -0.53125 h -1.84375 V -3.96875 H 0.65625 v 3.046875 H -0.046875 V 0 H 2.5 V -0.921875 H 1.796875 v -2.1875 C 2.09375,-3.515625 2.40625,-3.90625 2.84375,-3.90625 c 0.5,0 0.578125,0.296875 0.578125,0.84375 V 0 Z m 0,0"
+ id="path200"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.828125,-1.46875 c 0,-1.15625 -1.359375,-1.390625 -2.203125,-1.625 -0.25,-0.0625 -0.859375,-0.21875 -0.859375,-0.5625 0,-0.421875 0.59375,-0.4375 0.921875,-0.4375 0.234375,0 0.546875,0.046875 0.796875,0.09375 v 0.453125 H 4.4375 v -1.1875 c -0.609375,-0.1875 -1.234375,-0.28125 -1.765625,-0.28125 -0.859375,0 -2,0.34375 -2,1.484375 0,1.125 1.375,1.375 2.171875,1.609375 0.25,0.078125 0.859375,0.234375 0.859375,0.5625 0,0.484375 -0.75,0.546875 -1.125,0.546875 -0.296875,0 -0.671875,-0.0625 -0.96875,-0.140625 V -1.46875 h -0.96875 v 1.296875 C 1.3125,-0.015625 1.96875,0.09375 2.5625,0.09375 c 0.875,0 2.265625,-0.328125 2.265625,-1.5625 z m 0,0"
+ id="path203"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.8125,-0.015625 V -0.96875 C 4.3125,-0.875 3.984375,-0.8125 3.640625,-0.8125 2.90625,-0.8125 2.6875,-0.921875 2.6875,-1.65625 V -3.875 H 4.28125 V -4.796875 H 2.6875 V -5.78125 h -1.125 v 0.984375 H 0.40625 V -3.875 H 1.5625 v 2.078125 c 0,1.4375 0.453125,1.890625 1.890625,1.890625 0.421875,0 0.828125,-0.03125 1.359375,-0.109375 z m 0,0"
+ id="path206"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.328125,0 V -0.921875 H 4.78125 l -1.3125,-2.03125 c 0.6875,-0.390625 1.171875,-1.0625 1.171875,-1.921875 0,-1.359375 -1.328125,-1.65625 -2.25,-1.65625 H 0.09375 v 0.921875 h 0.625 v 4.6875 h -0.625 V 0 h 2.390625 v -0.921875 h -0.625 V -2.65625 H 2.375 L 4.09375,0 Z m -1.875,-4.734375 c 0,0.703125 -0.671875,1.140625 -1.3125,1.140625 H 1.859375 V -5.609375 H 2.25 c 0.609375,0 1.203125,0.203125 1.203125,0.875 z m 0,0"
+ id="path209"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.796875,-0.21875 V -1.203125 C 4.140625,-0.9375 3.65625,-0.8125 3.171875,-0.8125 2.265625,-0.8125 1.75,-1.21875 1.640625,-2.078125 H 4.78125 C 4.78125,-3.5625 4.5625,-5 2.765625,-5 c -1.484375,0 -2.3125,1.265625 -2.3125,2.609375 0,1.640625 1.015625,2.484375 2.609375,2.484375 0.5625,0 1.109375,-0.109375 1.734375,-0.3125 z m -1.21875,-2.796875 h -1.90625 c 0.109375,-0.578125 0.4375,-1.0625 1.03125,-1.0625 0.640625,0 0.859375,0.421875 0.875,1.0625 z m 0,0"
+ id="path212"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-8"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.171875,-0.09375 -0.125,-0.796875 C 4.96875,-0.875 4.75,-0.8125 4.671875,-0.8125 c -0.328125,0 -0.28125,-0.328125 -0.28125,-0.578125 V -3.3125 C 4.390625,-4.5625 3.84375,-5 2.640625,-5 2.046875,-5 1.46875,-4.875 0.8125,-4.625 v 1.0625 C 1.5,-3.921875 1.96875,-4.078125 2.46875,-4.078125 c 0.578125,0 0.796875,0.1875 0.796875,0.765625 v 0.234375 h -0.375 c -0.984375,0 -2.46875,0.375 -2.46875,1.75 0,0.90625 0.796875,1.390625 1.609375,1.390625 0.546875,0 1.046875,-0.234375 1.453125,-0.53125 0.171875,0.328125 0.46875,0.53125 0.875,0.53125 0.140625,0 0.25,-0.015625 0.359375,-0.03125 C 4.828125,0 4.9375,-0.03125 5.171875,-0.09375 Z M 3.265625,-1.3125 c -0.3125,0.25 -0.65625,0.421875 -1.015625,0.421875 -0.390625,0 -0.671875,-0.21875 -0.671875,-0.578125 0,-0.765625 1.015625,-0.78125 1.578125,-0.78125 h 0.109375 z m 0,0"
+ id="path215"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-9"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.640625,0 V -0.921875 H 3.1875 v -6.0625 H 0.578125 V -6.0625 h 1.46875 v 5.140625 H 0.578125 V 0 Z m 0,0"
+ id="path218"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-10"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.546875,-5.890625 V -6.875 c -0.53125,-0.15625 -0.984375,-0.21875 -1.4375,-0.21875 -1.84375,0 -2.046875,1.25 -2.0625,2.640625 H 0.8125 v 0.921875 h 1.234375 v 2.609375 H 0.59375 V 0 H 4.640625 V -0.921875 H 3.1875 V -3.53125 H 4.859375 V -4.453125 H 3.1875 V -4.8125 c 0,-0.84375 0.125,-1.359375 1,-1.359375 0.390625,0 0.78125,0.078125 1.359375,0.28125 z m 0,0"
+ id="path221"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-11"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5,-3.296875 v -1.5625 C 4.578125,-4.953125 4.28125,-5 3.984375,-5 3.34375,-5 2.828125,-4.734375 2.4375,-4.3125 V -4.890625 H 0.421875 V -3.96875 H 1.28125 v 3.046875 H 0.1875 V 0 H 3.734375 V -0.921875 H 2.4375 V -3.09375 c 0.390625,-0.53125 0.78125,-0.875 1.4375,-0.875 0.0625,0 0.125,0.015625 0.1875,0.015625 v 0.65625 z m 0,0"
+ id="path224"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-12"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.296875,-5.609375 V -6.53125 H 3.15625 v 0.921875 H 3.703125 V -2.3125 c 0,0.875 -0.15625,1.515625 -1.0625,1.515625 -0.84375,0 -1,-0.65625 -1,-1.484375 V -5.609375 H 2.21875 V -6.53125 H -0.0625 v 0.921875 h 0.578125 v 3.3125 c 0,1.40625 0.546875,2.421875 2.140625,2.421875 1.65625,0 2.078125,-1.1875 2.078125,-2.5625 v -3.171875 z m 0,0"
+ id="path227"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph2-13"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.640625,0 V -0.921875 H 3.1875 v -4.6875 H 4.640625 V -6.53125 h -4.0625 v 0.921875 h 1.46875 v 4.6875 H 0.578125 V 0 Z m 0,0"
+ id="path230"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path233"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.859375,0.578125 v -2.03125 h -0.625 V 0 h -3.25 V -1.453125 H 0.375 v 2.03125 z m 0,0"
+ id="path236"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.6875,-1.3125 C 4.6875,-2.953125 1.609375,-2.5 1.609375,-3.5 c 0,-0.5 0.6875,-0.59375 1.078125,-0.59375 0.28125,0 0.65625,0.0625 0.9375,0.109375 v 0.4375 H 4.28125 V -4.46875 c -0.484375,-0.140625 -1.09375,-0.25 -1.609375,-0.25 -0.859375,0 -1.84375,0.34375 -1.84375,1.34375 0,1.5625 3.015625,1.1875 3.015625,2.171875 0,0.5625 -0.828125,0.6875 -1.265625,0.6875 -0.34375,0 -0.796875,-0.078125 -1.125,-0.1875 v -0.46875 H 0.796875 V -0.15625 C 1.34375,-0.015625 2,0.09375 2.5625,0.09375 c 0.890625,0 2.125,-0.328125 2.125,-1.40625 z m 0,0"
+ id="path239"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5,-0.046875 4.921875,-0.5625 c -0.078125,0.03125 -0.171875,0.046875 -0.25,0.046875 -0.4375,0 -0.4375,-0.40625 -0.4375,-0.71875 V -3.15625 c 0,-1.15625 -0.453125,-1.546875 -1.59375,-1.546875 -0.5625,0 -1.140625,0.125 -1.671875,0.328125 v 0.703125 c 0.46875,-0.234375 0.96875,-0.40625 1.5,-0.40625 0.65625,0 0.9375,0.25 0.9375,0.90625 v 0.40625 H 2.890625 c -1,0 -2.328125,0.359375 -2.328125,1.578125 0,0.8125 0.71875,1.25 1.46875,1.25 0.5625,0 1.078125,-0.265625 1.5,-0.625 0.140625,0.390625 0.421875,0.625 0.828125,0.625 C 4.578125,0.0625 4.796875,0 5,-0.046875 Z M 3.40625,-1.09375 c -0.328125,0.28125 -0.71875,0.5 -1.15625,0.5 -0.453125,0 -0.8125,-0.265625 -0.8125,-0.734375 0,-0.84375 1.09375,-0.921875 1.71875,-0.921875 h 0.25 z m 0,0"
+ id="path242"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.40625,-5.953125 v -0.65625 C 4.984375,-6.734375 4.5625,-6.78125 4.109375,-6.78125 c -1.75,0 -1.90625,1.171875 -1.90625,2.625 h -1.25 v 0.625 h 1.25 V -0.625 H 0.734375 V 0 H 4.5 V -0.625 H 3.03125 v -2.90625 h 1.6875 v -0.625 H 3.046875 v -0.515625 c 0,-0.84375 0.140625,-1.5 1.140625,-1.5 0.421875,0 0.828125,0.078125 1.21875,0.21875 z m 0,0"
+ id="path245"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.640625,-0.171875 V -0.84375 c -0.46875,0.203125 -0.96875,0.328125 -1.46875,0.328125 -1.03125,0 -1.625,-0.515625 -1.6875,-1.5625 H 4.625 c 0,-1.34375 -0.203125,-2.625 -1.859375,-2.625 -1.375,0 -2.171875,1.171875 -2.171875,2.453125 0,1.5625 0.953125,2.34375 2.46875,2.34375 0.53125,0 1.078125,-0.109375 1.578125,-0.265625 z M 3.734375,-2.71875 H 1.5 c 0.078125,-0.6875 0.421875,-1.359375 1.203125,-1.359375 0.78125,0 1.03125,0.546875 1.03125,1.25 z m 0,0"
+ id="path248"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.671875,0 v -0.640625 c -0.34375,0.078125 -0.6875,0.125 -1.03125,0.125 -0.78125,0 -1.109375,-0.15625 -1.109375,-0.984375 V -3.875 H 4.140625 V -4.5 H 2.53125 V -5.484375 H 1.703125 V -4.5 h -1.15625 v 0.625 h 1.15625 v 2.234375 c 0,1.34375 0.390625,1.734375 1.75,1.734375 0.40625,0 0.8125,-0.03125 1.21875,-0.09375 z m 0,0"
+ id="path251"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.984375,-3.984375 V -4.59375 h -1.625 v 0.609375 h 0.375 L 2.65625,-1.21875 1.609375,-3.984375 H 1.90625 V -4.59375 H 0.234375 v 0.609375 H 0.75 l 1.5,3.78125 C 1.828125,0.875 1.75,1.03125 0.546875,1.03125 v 0.640625 c 1.015625,0 1.671875,-0.0625 2.078125,-1.09375 l 1.875,-4.5625 z m 0,0"
+ id="path254"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-8"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.03125,0.625 V 0 H 0.203125 v 0.625 z m 0,0"
+ id="path257"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-9"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.140625,-5.625 V -6.6875 H 2.09375 V -5.625 Z M 4.34375,0 V -0.625 H 3.03125 V -4.59375 H 0.828125 v 0.625 H 2.1875 V -0.625 H 0.734375 V 0 Z m 0,0"
+ id="path260"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-10"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.296875,0 v -0.625 h -0.5 v -2.75 c 0,-0.5625 -0.015625,-1.328125 -0.765625,-1.328125 -0.515625,0 -0.84375,0.546875 -1.046875,0.96875 H 2.953125 C 2.875,-4.15625 2.734375,-4.703125 2.21875,-4.703125 1.75,-4.703125 1.375,-4.09375 1.1875,-3.734375 V -4.59375 h -1.234375 v 0.625 h 0.5 V -0.625 h -0.5 V 0 H 1.6875 v -0.625 h -0.5 v -2.328125 c 0.125,-0.28125 0.5,-1.015625 0.84375,-1.015625 0.21875,0 0.21875,0.25 0.21875,0.40625 V 0 h 1.234375 v -0.625 h -0.5 v -2.34375 c 0.140625,-0.3125 0.46875,-1.015625 0.859375,-1.015625 0.21875,0 0.21875,0.21875 0.21875,0.390625 V 0 Z m 0,0"
+ id="path263"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-11"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.65625,-0.15625 v -0.6875 C 4.25,-0.6875 3.8125,-0.5625 3.375,-0.5625 c -1.046875,0 -1.90625,-0.671875 -1.90625,-1.765625 0,-0.984375 0.65625,-1.765625 1.671875,-1.765625 0.265625,0 0.53125,0.046875 0.78125,0.109375 v 0.4375 h 0.65625 v -0.9375 C 4.125,-4.625 3.65625,-4.71875 3.15625,-4.71875 c -1.46875,0 -2.578125,0.921875 -2.578125,2.4375 0,1.53125 1.15625,2.375 2.609375,2.375 0.5,0 0.984375,-0.09375 1.46875,-0.25 z m 0,0"
+ id="path266"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-12"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.78125,-2.296875 c 0,-1.375 -0.71875,-2.40625 -2.171875,-2.40625 -1.4375,0 -2.171875,1.03125 -2.171875,2.40625 0,1.359375 0.734375,2.390625 2.171875,2.390625 1.453125,0 2.171875,-1.03125 2.171875,-2.390625 z m -0.890625,0 c 0,0.828125 -0.296875,1.78125 -1.28125,1.78125 -0.984375,0 -1.28125,-0.96875 -1.28125,-1.78125 0,-0.828125 0.296875,-1.78125 1.28125,-1.78125 0.984375,0 1.28125,0.953125 1.28125,1.78125 z m 0,0"
+ id="path269"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-13"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.84375,-3.296875 V -4.59375 C 4.5625,-4.65625 4.265625,-4.703125 3.984375,-4.703125 c -0.734375,0 -1.296875,0.375 -1.703125,0.96875 V -4.59375 H 0.578125 v 0.625 H 1.4375 V -0.625 H 0.34375 V 0 H 3.578125 V -0.625 H 2.28125 V -2.984375 C 2.6875,-3.5625 3.125,-3.96875 3.875,-3.96875 c 0.109375,0 0.234375,0.015625 0.34375,0.046875 v 0.625 z m 0,0"
+ id="path272"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-14"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.875,-3.296875 V -3.84375 h -4.5 v 0.546875 z m 0,2.03125 v -0.5625 h -4.5 v 0.5625 z m 0,0"
+ id="path275"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-15"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.75,-3.140625 c 0,-1.34375 -0.453125,-3.296875 -2.140625,-3.296875 -1.6875,0 -2.140625,1.953125 -2.140625,3.296875 0,1.359375 0.453125,3.296875 2.140625,3.296875 C 4.3125,0.15625 4.75,-1.78125 4.75,-3.140625 Z m -0.875,0 c 0,0.46875 -0.03125,1.234375 -0.234375,1.8125 l -1.5625,-4.3125 c 0.15625,-0.09375 0.328125,-0.15625 0.53125,-0.15625 1.203125,0 1.265625,1.8125 1.265625,2.65625 z M 3.140625,-0.625 C 3,-0.53125 2.828125,-0.46875 2.609375,-0.46875 c -1.1875,0 -1.25,-1.828125 -1.25,-2.671875 0,-0.453125 0.03125,-1.203125 0.234375,-1.78125 z m 0,0"
+ id="path278"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-16"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.234375,0 v -1.25 h -1.25 V 0 Z m 0,0"
+ id="path281"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-17"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.671875,-1.640625 c 0,-0.90625 -0.65625,-1.40625 -1.359375,-1.8125 0.578125,-0.359375 1.109375,-0.890625 1.109375,-1.625 0,-0.96875 -0.75,-1.359375 -1.625,-1.359375 C 1.828125,-6.4375 1,-5.890625 1,-4.859375 1,-4.25 1.375,-3.765625 1.84375,-3.421875 1.171875,-3 0.671875,-2.390625 0.671875,-1.578125 c 0,1.125 0.90625,1.734375 1.953125,1.734375 1.078125,0 2.046875,-0.65625 2.046875,-1.796875 z M 3.65625,-4.9375 c 0,0.53125 -0.390625,0.9375 -0.8125,1.203125 C 2.375,-4 1.78125,-4.359375 1.78125,-4.96875 c 0,-0.546875 0.421875,-0.828125 0.9375,-0.828125 0.515625,0 0.9375,0.3125 0.9375,0.859375 z m 0.171875,3.46875 c 0,0.59375 -0.5625,1 -1.125,1 C 1.984375,-0.46875 1.5,-0.984375 1.5,-1.6875 c 0,-0.5625 0.390625,-1.046875 0.796875,-1.390625 0.59375,0.359375 1.53125,0.8125 1.53125,1.609375 z m 0,0"
+ id="path284"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-18"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.234375,-3.34375 v -1.25 h -1.25 v 1.25 z m 0,2.84375 v -0.75 h -1.25 V 0 H 2.5 c 0,0.328125 -0.09375,0.890625 -0.515625,0.921875 v 0.4375 C 3.015625,1.3125 3.234375,0.375 3.234375,-0.5 Z m 0,0"
+ id="path287"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-19"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.8125,-2.453125 c 0,-1.0625 -0.421875,-2.25 -1.671875,-2.25 -0.65625,0 -1.171875,0.421875 -1.5,0.96875 V -4.59375 h -1.4375 v 0.625 h 0.59375 v 5 h -0.59375 v 0.640625 h 2.03125 V 1.03125 h -0.59375 v -1.546875 c 0.3125,0.390625 0.75,0.609375 1.25,0.609375 1.375,0 1.921875,-1.375 1.921875,-2.546875 z m -0.875,0.09375 c 0,0.75 -0.203125,1.84375 -1.171875,1.84375 -0.4375,0 -0.84375,-0.3125 -1.125,-0.625 V -3.09375 C 1.9375,-3.546875 2.375,-3.984375 2.953125,-3.984375 c 0.859375,0 0.984375,0.96875 0.984375,1.625 z m 0,0"
+ id="path290"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-20"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.5,0 V -0.625 H 3.03125 V -6.6875 H 0.734375 v 0.625 H 2.1875 V -0.625 H 0.734375 V 0 Z m 0,0"
+ id="path293"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-21"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.09375,0 v -0.625 h -0.625 V -6.6875 H 3 v 0.625 h 0.625 v 1.984375 c -0.3125,-0.375 -0.75,-0.625 -1.25,-0.625 -1.375,0 -1.9375,1.359375 -1.9375,2.546875 0,1.0625 0.4375,2.25 1.6875,2.25 0.65625,0 1.171875,-0.4375 1.5,-0.96875 V 0 Z M 3.625,-1.5 c -0.3125,0.453125 -0.75,0.890625 -1.328125,0.890625 -0.859375,0 -0.96875,-0.96875 -0.96875,-1.625 0,-0.75 0.203125,-1.84375 1.15625,-1.84375 0.453125,0 0.859375,0.3125 1.140625,0.640625 z m 0,0"
+ id="path296"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-22"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.53125,-4.859375 -0.25,-0.8125 -1.3125,0.59375 c 0.125,0.15625 0.171875,0.296875 0.171875,0.5 z m -1.5,-1.703125 H 2.1875 l 0.171875,1.40625 c 0.078125,-0.03125 0.15625,-0.046875 0.25,-0.046875 0.09375,0 0.1875,0.015625 0.265625,0.046875 z M 4.0625,-3.40625 3.09375,-4.46875 C 3,-4.3125 2.84375,-4.203125 2.6875,-4.140625 l 0.6875,1.21875 z M 2.25,-5.078125 l -1.296875,-0.59375 -0.25,0.8125 1.375,0.28125 c 0,-0.203125 0.046875,-0.34375 0.171875,-0.5 z m 0.296875,0.9375 C 2.375,-4.203125 2.21875,-4.3125 2.125,-4.46875 l -0.953125,1.0625 0.671875,0.484375 z m 0,0"
+ id="path299"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-23"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.921875,-4.921875 v -1.3125 H 0.3125 v 1.3125 h 0.625 v -0.6875 H 2.203125 V -0.625 H 1.46875 V 0 h 2.296875 v -0.625 h -0.71875 v -4.984375 h 1.25 v 0.6875 z m 0,0"
+ id="path302"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-24"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.71875,-1.53125 c 0,-1.921875 -3.21875,-2.125 -3.21875,-3.4375 0,-0.640625 0.625,-0.765625 1.140625,-0.765625 0.34375,0 0.671875,0.0625 1.015625,0.15625 v 0.5 h 0.625 V -6.09375 C 3.734375,-6.265625 3.1875,-6.375 2.625,-6.375 c -0.984375,0 -1.890625,0.421875 -1.890625,1.546875 0,1.84375 3.15625,2.1875 3.15625,3.4375 C 3.890625,-0.6875 3.09375,-0.5 2.53125,-0.5 2.125,-0.5 1.71875,-0.59375 1.328125,-0.734375 v -0.5625 h -0.625 v 1.125 c 0.578125,0.15625 1.1875,0.296875 1.8125,0.296875 1.03125,0 2.203125,-0.4375 2.203125,-1.65625 z m 0,0"
+ id="path305"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-25"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.59375,1.25 V 0.671875 C 2.90625,0.3125 2.296875,-1.140625 2.296875,-2.71875 c 0,-1.5625 0.59375,-3.046875 2.296875,-3.390625 V -6.6875 c -2.03125,0.234375 -3.140625,2.046875 -3.140625,3.96875 0,1.9375 1.109375,3.734375 3.140625,3.96875 z m 0,0"
+ id="path308"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-26"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.765625,-2.71875 c 0,-1.890625 -1.125,-3.734375 -3.140625,-3.96875 v 0.578125 c 1.703125,0.34375 2.296875,1.828125 2.296875,3.390625 0,1.578125 -0.59375,3.03125 -2.296875,3.390625 V 1.25 C 2.65625,1.015625 3.765625,-0.796875 3.765625,-2.71875 Z m 0,0"
+ id="path311"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-27"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.453125,0 V -0.625 H 3.296875 V -6.4375 L 1.34375,-5.609375 V -5 L 2.453125,-5.40625 V -0.625 H 1.296875 V 0 Z m 0,0"
+ id="path314"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-28"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.34375,-2.28125 v -0.5625 H 0.890625 v 0.5625 z m 0,0"
+ id="path317"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-29"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.859375,-0.0625 V -0.625 L 1.28125,-2.5625 4.859375,-4.5 V -5.0625 L 0.375,-2.65625 v 0.1875 z m 0,0"
+ id="path320"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-30"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.875,-2.28125 v -0.5625 H 2.90625 V -4.796875 H 2.34375 V -2.84375 H 0.375 v 0.5625 h 1.96875 v 1.984375 h 0.5625 V -2.28125 Z m 0,0"
+ id="path323"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-31"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.34375,1.25 V 0.625 c -0.53125,0 -1.5,0.09375 -1.5,-0.6875 0,-0.484375 0.203125,-0.96875 0.203125,-1.453125 0,-0.59375 -0.28125,-1.015625 -0.84375,-1.203125 0.5625,-0.1875 0.84375,-0.59375 0.84375,-1.171875 0,-0.5 -0.203125,-0.984375 -0.203125,-1.484375 0,-0.78125 0.953125,-0.6875 1.5,-0.6875 v -0.625 H 3.875 c -0.828125,0 -1.78125,0.203125 -1.78125,1.21875 0,0.5625 0.234375,1.109375 0.234375,1.65625 0,0.828125 -0.75,0.78125 -1.34375,0.78125 v 0.625 c 0.59375,0 1.34375,-0.03125 1.34375,0.765625 0,0.578125 -0.234375,1.109375 -0.234375,1.671875 0,1 0.984375,1.21875 1.78125,1.21875 z m 0,0"
+ id="path326"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-32"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.984375,-3.984375 V -4.59375 h -1.625 v 0.609375 h 0.4375 l -1.15625,3.0625 -1.109375,-3.0625 h 0.375 V -4.59375 H 0.234375 v 0.609375 H 0.6875 l 1.46875,3.96875 h 0.859375 l 1.515625,-3.96875 z m 0,0"
+ id="path329"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph3-33"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.234375,-2.40625 v -0.625 C 3.640625,-3.03125 2.90625,-3 2.90625,-3.8125 2.90625,-4.359375 3.125,-4.90625 3.125,-5.46875 3.125,-6.453125 2.15625,-6.6875 1.34375,-6.6875 H 0.890625 v 0.625 c 0.546875,0 1.484375,-0.09375 1.484375,0.6875 0,0.5 -0.203125,0.984375 -0.203125,1.484375 0,0.578125 0.28125,0.984375 0.84375,1.171875 -0.5625,0.1875 -0.84375,0.59375 -0.84375,1.1875 0,0.5 0.203125,0.96875 0.203125,1.46875 0,0.765625 -0.953125,0.6875 -1.484375,0.6875 V 1.25 H 1.34375 c 0.8125,0 1.78125,-0.203125 1.78125,-1.21875 0,-0.5625 -0.21875,-1.09375 -0.21875,-1.671875 0,-0.796875 0.75,-0.765625 1.328125,-0.765625 z m 0,0"
+ id="path332"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph4-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path335"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph4-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 6.59375,-2.625 V -3.265625 H 0.703125 V -2.625 Z m 0,0"
+ id="path338"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph4-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5,-2.953125 c 0,-1.1875 -0.953125,-2.125 -2.140625,-2.125 -1.203125,0 -2.15625,0.9375 -2.15625,2.125 0,1.203125 0.953125,2.140625 2.15625,2.140625 C 4.046875,-0.8125 5,-1.75 5,-2.953125 Z m -0.5625,0 c 0,0.890625 -0.71875,1.59375 -1.578125,1.59375 -0.890625,0 -1.59375,-0.703125 -1.59375,-1.59375 0,-0.875 0.703125,-1.578125 1.59375,-1.578125 0.859375,0 1.578125,0.703125 1.578125,1.578125 z m 0,0"
+ id="path341"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph5-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path344"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph5-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.140625,-6.34375 c 0,-0.6875 -0.390625,-1.078125 -1.078125,-1.078125 -0.34375,0 -0.6875,0.078125 -0.984375,0.21875 -1.765625,0.71875 -1.875,2.421875 -2.125,4.046875 C 0.640625,-1.109375 0.375,0.953125 -0.0625,2.984375 L 0.015625,3.09375 C 0.28125,2.984375 0.5625,2.890625 0.84375,2.828125 0.90625,1.765625 1.03125,0.71875 1.171875,-0.3125 1.53125,0.015625 2,0.15625 2.46875,0.15625 3.796875,0.15625 5,-0.875 5,-2.234375 5,-3.28125 4.203125,-3.90625 3.21875,-3.921875 L 3.234375,-4.03125 c 0.96875,-0.328125 1.90625,-1.1875 1.90625,-2.3125 z m -0.78125,0.265625 c 0,1.21875 -1.015625,2.03125 -2.171875,2.03125 -0.03125,0.125 -0.0625,0.265625 -0.109375,0.375 L 2.15625,-3.59375 C 2.328125,-3.671875 2.5,-3.703125 2.6875,-3.703125 c 0.890625,0 1.4375,0.53125 1.4375,1.4375 C 4.125,-1.25 3.546875,-0.125 2.40625,-0.125 c -0.640625,0 -1.03125,-0.359375 -1.03125,-1 0,-1.109375 0.59375,-5.109375 1.578125,-5.734375 0.171875,-0.109375 0.375,-0.1875 0.578125,-0.1875 0.578125,0 0.828125,0.4375 0.828125,0.96875 z m 0,0"
+ id="path347"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph5-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.359375,-7.78125 H 3.75 l -3.046875,9.625 H 1.3125 Z m 0,0"
+ id="path350"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph5-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 6.046875,-4.5 C 5.96875,-4.671875 5.890625,-4.84375 5.796875,-5 H 5.6875 C 5.53125,-4.265625 5.03125,-3.4375 4.640625,-2.796875 L 4.5625,-2.828125 c 0.015625,-0.84375 0.234375,-2.328125 -0.984375,-2.328125 -1.828125,0 -3.28125,2.5 -3.28125,4.140625 0,0.65625 0.21875,1.1875 0.953125,1.1875 1,0 2,-0.875 2.625,-1.59375 l 0.046875,0.03125 c 0,0.359375 -0.078125,1.5625 0.484375,1.5625 0.515625,0 1.25,-0.765625 1.5625,-1.09375 V -1 L 5.90625,-1.0625 H 5.828125 C 5.625,-0.859375 5.375,-0.59375 5.078125,-0.59375 4.59375,-0.59375 4.625,-2 4.625,-2.359375 5.15625,-3.03125 5.65625,-3.734375 6.046875,-4.5 Z M 3.90625,-1.78125 c -0.453125,0.546875 -1.328125,1.46875 -2.109375,1.46875 -0.5625,0 -0.703125,-0.46875 -0.703125,-0.9375 0,-0.953125 0.765625,-3.515625 1.953125,-3.515625 0.9375,0 0.859375,2.015625 0.859375,2.671875 z m 0,0"
+ id="path353"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph5-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.984375,-3.125 c 0,-1.984375 -2.5625,-2.390625 -2.5625,-3.65625 0,-0.453125 0.578125,-0.625 0.953125,-0.625 0.375,0 0.75,0.125 1.0625,0.328125 l 0.125,-0.0625 C 4.53125,-7.28125 4.484375,-7.421875 4.421875,-7.5625 4.15625,-7.625 3.875,-7.65625 3.609375,-7.65625 c -0.671875,0 -1.96875,0.28125 -1.96875,1.140625 0,0.640625 0.78125,1.140625 1.25,1.453125 L 2.875,-5 c -1.546875,0.359375 -2.53125,1.6875 -2.53125,3.25 0,1.171875 0.484375,1.921875 1.71875,1.921875 1.71875,0 2.921875,-1.6875 2.921875,-3.296875 z M 4.15625,-2.9375 c 0,1.046875 -0.53125,2.8125 -1.8125,2.8125 -0.921875,0 -1.15625,-0.953125 -1.15625,-1.703125 0,-1.390625 0.46875,-2.65625 1.921875,-3.0625 0.671875,0.53125 1.046875,1.0625 1.046875,1.953125 z m 0,0"
+ id="path356"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph6-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path359"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph6-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 6.59375,-3.78125 V -4.421875 H 0.703125 v 0.640625 z m 0,2.3125 V -2.109375 H 0.703125 v 0.640625 z m 0,0"
+ id="path362"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph6-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 6.59375,-2.625 v -0.640625 h -2.625 V -5.875 H 3.328125 v 2.609375 h -2.625 V -2.625 h 2.625 V 0 H 3.96875 v -2.625 z m 0,0"
+ id="path365"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph6-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 7.21875,-0.0625 c -0.671875,-1.203125 -1.1875,-2.53125 -1.734375,-3.796875 -0.53125,-1.21875 -1.109375,-2.46875 -1.53125,-3.75 h -0.28125 c -0.546875,1.375 -1.15625,2.703125 -1.75,4.046875 -0.53125,1.15625 -1.03125,2.375 -1.625,3.5 L 0.375,0.046875 C 1.53125,0 2.6875,0 3.84375,0 4.953125,0 6.046875,0.015625 7.15625,0.046875 Z M 5.859375,-0.40625 h -4.71875 c 0.71875,-1.9375 1.5,-3.84375 2.328125,-5.75 h 0.078125 c 0.8125,1.890625 1.59375,3.8125 2.3125,5.75 z m 0,0"
+ id="path368"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path371"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.71875,0 v -1.015625 h -0.5625 l -1.6875,-6.125 H 2.25 l -1.6875,6.125 H 0.015625 V 0 h 2.4375 v -1.015625 h -0.6875 C 1.890625,-1.40625 2,-1.8125 2.109375,-2.203125 H 3.5625 c 0.109375,0.390625 0.21875,0.796875 0.34375,1.1875 H 3.21875 V 0 Z M 3.265625,-3.3125 H 2.40625 C 2.546875,-3.875 2.6875,-4.453125 2.828125,-5.03125 2.984375,-4.453125 3.125,-3.875 3.265625,-3.3125 Z m 0,0"
+ id="path374"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.671875,0 V -1.015625 H 4.96875 L 3.234375,-2.9375 4.46875,-4.34375 h 0.890625 v -1.015625 h -2.5625 v 1.015625 h 0.25 L 2.0625,-3.234375 v -4.40625 H 0.15625 V -6.625 H 0.8125 v 5.609375 H 0.15625 V 0 h 2.5625 V -1.015625 H 2.0625 v -1.34375 l 1.203125,1.34375 H 3.125 V 0 Z m 0,0"
+ id="path377"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.65625,-0.09375 5.515625,-0.984375 c -0.078125,0.03125 -0.3125,0.09375 -0.40625,0.09375 -0.359375,0 -0.3125,-0.359375 -0.3125,-0.625 V -3.625 c 0,-1.359375 -0.59375,-1.84375 -1.90625,-1.84375 -0.640625,0 -1.28125,0.140625 -2,0.40625 v 1.15625 c 0.75,-0.375 1.265625,-0.546875 1.8125,-0.546875 0.640625,0 0.859375,0.203125 0.859375,0.828125 v 0.265625 H 3.15625 c -1.078125,0 -2.703125,0.40625 -2.703125,1.890625 0,1.015625 0.890625,1.546875 1.765625,1.546875 0.59375,0 1.140625,-0.265625 1.59375,-0.59375 0.171875,0.359375 0.5,0.59375 0.96875,0.59375 0.140625,0 0.265625,-0.03125 0.390625,-0.046875 C 5.28125,0 5.40625,-0.03125 5.65625,-0.09375 Z M 3.5625,-1.4375 c -0.328125,0.265625 -0.703125,0.46875 -1.109375,0.46875 -0.421875,0 -0.71875,-0.234375 -0.71875,-0.640625 0,-0.828125 1.09375,-0.859375 1.71875,-0.859375 H 3.5625 Z m 0,0"
+ id="path380"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.765625,0 V -1.015625 H 5 v -2.59375 C 5,-4.625 4.609375,-5.46875 3.40625,-5.46875 c -0.640625,0 -1.09375,0.28125 -1.4375,0.6875 V -5.359375 H -0.046875 V -4.34375 H 0.71875 v 3.328125 H -0.046875 V 0 H 2.71875 v -1.015625 h -0.75 V -3.40625 c 0.328125,-0.4375 0.65625,-0.875 1.15625,-0.875 0.546875,0 0.625,0.328125 0.625,0.9375 V 0 Z m 0,0"
+ id="path383"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.265625,-0.015625 V -1.0625 c -0.546875,0.109375 -0.90625,0.171875 -1.28125,0.171875 -0.796875,0 -1.046875,-0.125 -1.046875,-0.921875 v -2.421875 h 1.75 V -5.25 h -1.75 V -6.328125 H 1.703125 V -5.25 H 0.4375 v 1.015625 h 1.265625 v 2.265625 c 0,1.578125 0.5,2.078125 2.078125,2.078125 0.453125,0 0.890625,-0.046875 1.484375,-0.125 z m 0,0"
+ id="path386"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph7-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.703125,0 v -1.015625 h -0.65625 v -4.34375 H 3.15625 V -4.34375 H 3.8125 v 2.375 C 3.484375,-1.515625 3.03125,-1.078125 2.53125,-1.078125 1.984375,-1.078125 1.890625,-1.40625 1.890625,-2 v -3.359375 h -1.875 v 1.015625 h 0.65625 V -1.75 c 0,1.015625 0.375,1.859375 1.578125,1.859375 0.65625,0 1.15625,-0.28125 1.5625,-0.734375 V 0 Z m 0,0"
+ id="path389"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path392"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.125,-1.4375 c 0,-1.796875 -3.359375,-1.28125 -3.359375,-2.390625 0,-0.5625 0.75,-0.640625 1.171875,-0.640625 0.3125,0 0.734375,0.046875 1.03125,0.109375 V -3.875 H 4.6875 V -4.890625 C 4.15625,-5.046875 3.484375,-5.15625 2.921875,-5.15625 c -0.9375,0 -2.015625,0.375 -2.015625,1.453125 0,1.71875 3.296875,1.296875 3.296875,2.390625 0,0.609375 -0.90625,0.75 -1.375,0.75 -0.390625,0 -0.875,-0.078125 -1.234375,-0.203125 V -1.28125 H 0.875 v 1.125 c 0.59375,0.140625 1.3125,0.265625 1.921875,0.265625 0.984375,0 2.328125,-0.375 2.328125,-1.546875 z m 0,0"
+ id="path395"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.21875,-2.515625 c 0,-1.5 -0.765625,-2.625 -2.359375,-2.625 -1.578125,0 -2.375,1.125 -2.375,2.625 0,1.484375 0.796875,2.625 2.375,2.625 1.59375,0 2.359375,-1.140625 2.359375,-2.625 z m -0.953125,0 c 0,0.90625 -0.328125,1.953125 -1.40625,1.953125 -1.078125,0 -1.390625,-1.0625 -1.390625,-1.953125 0,-0.890625 0.3125,-1.9375 1.390625,-1.9375 1.078125,0 1.40625,1.03125 1.40625,1.9375 z m 0,0"
+ id="path398"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.921875,0 V -0.6875 H 3.3125 v -6.625 H 0.796875 V -6.625 H 2.40625 v 5.9375 H 0.796875 V 0 Z m 0,0"
+ id="path401"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.453125,-4.359375 V -5.03125 h -1.78125 v 0.671875 H 4.15625 l -1.265625,3.34375 -1.21875,-3.34375 h 0.40625 V -5.03125 h -1.8125 v 0.671875 H 0.75 l 1.609375,4.34375 h 0.9375 l 1.65625,-4.34375 z m 0,0"
+ id="path404"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.078125,-0.203125 v -0.71875 C 4.5625,-0.703125 4.03125,-0.5625 3.46875,-0.5625 2.328125,-0.5625 1.6875,-1.140625 1.625,-2.28125 h 3.4375 c 0,-1.46875 -0.234375,-2.859375 -2.03125,-2.859375 -1.515625,0 -2.375,1.28125 -2.375,2.6875 0,1.703125 1.03125,2.5625 2.6875,2.5625 0.59375,0 1.1875,-0.125 1.734375,-0.3125 z m -1,-2.765625 h -2.4375 c 0.078125,-0.75 0.46875,-1.484375 1.3125,-1.484375 0.859375,0 1.125,0.59375 1.125,1.359375 z m 0,0"
+ id="path407"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.171875,-1.671875 C 5.171875,-3.78125 1.640625,-4 1.640625,-5.4375 c 0,-0.703125 0.6875,-0.828125 1.25,-0.828125 0.375,0 0.734375,0.0625 1.09375,0.15625 V -5.5625 h 0.6875 V -6.671875 C 4.09375,-6.84375 3.484375,-6.96875 2.875,-6.96875 c -1.09375,0 -2.078125,0.453125 -2.078125,1.6875 0,2.015625 3.46875,2.390625 3.46875,3.75 0,0.78125 -0.875,0.984375 -1.5,0.984375 -0.4375,0 -0.890625,-0.109375 -1.3125,-0.265625 v -0.609375 h -0.6875 V -0.1875 C 1.40625,-0.015625 2.078125,0.125 2.75,0.125 c 1.125,0 2.421875,-0.46875 2.421875,-1.796875 z m 0,0"
+ id="path410"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.109375,0 v -0.703125 c -0.375,0.078125 -0.75,0.140625 -1.125,0.140625 -0.859375,0 -1.21875,-0.171875 -1.21875,-1.078125 v -2.59375 H 4.53125 v -0.6875 H 2.765625 V -6 h -0.90625 v 1.078125 H 0.59375 v 0.6875 h 1.265625 v 2.4375 c 0,1.484375 0.4375,1.90625 1.921875,1.90625 C 4.21875,0.109375 4.671875,0.0625 5.109375,0 Z m 0,0"
+ id="path413"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-8"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.265625,-2.6875 c 0,-1.15625 -0.453125,-2.453125 -1.828125,-2.453125 -0.71875,0 -1.28125,0.46875 -1.65625,1.046875 v -0.9375 h -1.5625 v 0.6875 H 0.875 V 1.140625 H 0.21875 v 0.6875 H 2.4375 v -0.6875 H 1.78125 V -0.5625 c 0.359375,0.421875 0.84375,0.671875 1.375,0.671875 1.515625,0 2.109375,-1.5 2.109375,-2.796875 z M 4.3125,-2.578125 c 0,0.828125 -0.234375,2.015625 -1.28125,2.015625 -0.484375,0 -0.921875,-0.34375 -1.25,-0.6875 V -3.390625 C 2.125,-3.875 2.609375,-4.359375 3.234375,-4.359375 c 0.9375,0 1.078125,1.0625 1.078125,1.78125 z m 0,0"
+ id="path416"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-9"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.796875,0 V -0.6875 H 5.25 v -3 c 0,-0.625 -0.015625,-1.453125 -0.84375,-1.453125 -0.5625,0 -0.921875,0.59375 -1.140625,1.046875 H 3.234375 C 3.15625,-4.546875 3,-5.140625 2.421875,-5.140625 c -0.5,0 -0.921875,0.671875 -1.125,1.046875 v -0.9375 h -1.34375 v 0.6875 h 0.53125 v 3.65625 h -0.53125 V 0 H 1.84375 V -0.6875 H 1.296875 v -2.546875 c 0.125,-0.3125 0.546875,-1.109375 0.921875,-1.109375 0.234375,0 0.25,0.28125 0.25,0.453125 V 0 H 3.8125 V -0.6875 H 3.265625 V -3.25 c 0.15625,-0.34375 0.515625,-1.109375 0.9375,-1.109375 0.234375,0 0.25,0.25 0.25,0.421875 V 0 Z m 0,0"
+ id="path419"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-10"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.578125,0 v -0.6875 h -0.6875 v -6.625 H 3.28125 v 0.6875 h 0.6875 v 2.171875 c -0.34375,-0.421875 -0.828125,-0.6875 -1.375,-0.6875 -1.5,0 -2.109375,1.484375 -2.109375,2.78125 0,1.171875 0.46875,2.46875 1.84375,2.46875 0.71875,0 1.28125,-0.484375 1.640625,-1.0625 V 0 Z M 3.96875,-1.640625 c -0.34375,0.5 -0.828125,0.96875 -1.453125,0.96875 -0.9375,0 -1.046875,-1.0625 -1.046875,-1.765625 0,-0.828125 0.203125,-2.015625 1.25,-2.015625 0.5,0 0.9375,0.328125 1.25,0.6875 z m 0,0"
+ id="path422"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-11"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.546875,0 v -1.375 h -1.375 V 0 Z m 0,0"
+ id="path425"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-12"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.359375,0 v -0.671875 h -0.625 L 3.34375,-2.65625 4.53125,-4.359375 H 5.171875 V -5.03125 H 3.125 v 0.671875 h 0.5 l -0.75,1.0625 -0.71875,-1.0625 H 2.625 V -5.03125 H 0.59375 v 0.671875 h 0.625 L 2.421875,-2.65625 1,-0.671875 H 0.359375 V 0 H 2.40625 V -0.671875 H 1.921875 L 2.875,-2 3.8125,-0.671875 H 3.328125 V 0 Z m 0,0"
+ id="path428"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-13"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.4375,-6.15625 V -7.3125 H 2.296875 v 1.15625 z M 4.75,0 V -0.6875 H 3.3125 V -5.03125 H 0.90625 v 0.6875 h 1.5 V -0.6875 H 0.796875 V 0 Z m 0,0"
+ id="path431"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-14"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.09375,-0.15625 v -0.765625 c -0.453125,0.171875 -0.921875,0.3125 -1.40625,0.3125 -1.140625,0 -2.078125,-0.75 -2.078125,-1.9375 0,-1.078125 0.71875,-1.921875 1.828125,-1.921875 0.296875,0 0.578125,0.046875 0.859375,0.109375 V -3.875 h 0.71875 v -1.03125 c -0.5,-0.15625 -1.03125,-0.25 -1.5625,-0.25 -1.59375,0 -2.828125,1 -2.828125,2.65625 0,1.6875 1.265625,2.609375 2.859375,2.609375 C 4.03125,0.109375 4.5625,0 5.09375,-0.15625 Z m 0,0"
+ id="path434"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-15"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.296875,-4.921875 c 0,-1.515625 -1.140625,-1.890625 -2.375,-1.890625 H 0.3125 V -6.125 H 1 v 5.4375 H 0.3125 V 0 h 2.28125 v -0.6875 h -0.6875 v -2 c 1.40625,0 3.390625,-0.328125 3.390625,-2.234375 z m -0.96875,0.03125 c 0,1.078125 -0.96875,1.515625 -1.859375,1.515625 h -0.5625 v -2.75 H 2.8125 c 0.734375,0 1.515625,0.3125 1.515625,1.234375 z m 0,0"
+ id="path437"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-16"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.296875,-3.59375 v -1.4375 c -0.3125,-0.0625 -0.625,-0.109375 -0.9375,-0.109375 -0.796875,0 -1.421875,0.40625 -1.859375,1.046875 v -0.9375 H 0.625 v 0.6875 H 1.578125 V -0.6875 H 0.375 V 0 H 3.921875 V -0.6875 H 2.5 V -3.265625 C 2.9375,-3.90625 3.421875,-4.34375 4.25,-4.34375 c 0.109375,0 0.25,0.03125 0.359375,0.046875 v 0.703125 z m 0,0"
+ id="path440"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-17"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.03125,1.359375 v -0.625 C 3.171875,0.34375 2.515625,-1.25 2.515625,-2.96875 c 0,-1.71875 0.640625,-3.34375 2.515625,-3.71875 v -0.625 c -2.234375,0.25 -3.4375,2.234375 -3.4375,4.34375 0,2.109375 1.203125,4.078125 3.4375,4.328125 z m 0,0"
+ id="path443"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-18"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.125,-2.96875 c 0,-2.078125 -1.234375,-4.09375 -3.4375,-4.34375 v 0.625 c 1.859375,0.375 2.515625,2 2.515625,3.71875 0,1.71875 -0.65625,3.3125 -2.515625,3.703125 v 0.625 C 2.90625,1.109375 4.125,-0.875 4.125,-2.96875 Z m 0,0"
+ id="path446"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-19"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.296875,-0.1875 v -0.75 C 4.828125,-0.75 4.3125,-0.59375 3.78125,-0.59375 c -1.40625,0 -2.390625,-1.4375 -2.390625,-2.84375 0,-1.25 0.765625,-2.828125 2.109375,-2.828125 0.34375,0 0.703125,0.0625 1.03125,0.15625 V -5.5625 h 0.6875 v -1.125 c -0.546875,-0.15625 -1.109375,-0.28125 -1.6875,-0.28125 -1.875,0 -3.109375,1.71875 -3.109375,3.59375 0,1.875 1.28125,3.5 3.140625,3.5 0.59375,0 1.1875,-0.109375 1.734375,-0.3125 z m 0,0"
+ id="path449"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-20"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.546875,0 V -0.6875 H 4.890625 V -5.03125 H 3.3125 v 0.6875 H 3.96875 V -1.75 c -0.328125,0.46875 -0.828125,1 -1.4375,1 -0.703125,0 -0.796875,-0.5 -0.796875,-1.09375 v -3.1875 h -1.5625 v 0.6875 h 0.65625 v 2.765625 c 0,0.953125 0.34375,1.6875 1.421875,1.6875 0.765625,0 1.328125,-0.421875 1.71875,-1.0625 V 0 Z m 0,0"
+ id="path452"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-21"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.46875,-0.046875 -0.078125,-0.5625 c -0.09375,0.015625 -0.1875,0.046875 -0.28125,0.046875 -0.46875,0 -0.46875,-0.4375 -0.46875,-0.796875 v -2.09375 c 0,-1.265625 -0.5,-1.6875 -1.75,-1.6875 -0.625,0 -1.25,0.140625 -1.828125,0.359375 v 0.765625 c 0.515625,-0.265625 1.0625,-0.4375 1.640625,-0.4375 0.703125,0 1.03125,0.265625 1.03125,0.984375 v 0.4375 H 3.15625 c -1.078125,0 -2.53125,0.40625 -2.53125,1.734375 0,0.875 0.765625,1.375 1.59375,1.375 0.609375,0 1.1875,-0.3125 1.65625,-0.6875 0.15625,0.421875 0.4375,0.6875 0.90625,0.6875 0.234375,0 0.46875,-0.078125 0.6875,-0.125 z m -1.734375,-1.15625 c -0.359375,0.3125 -0.796875,0.5625 -1.28125,0.5625 -0.484375,0 -0.875,-0.296875 -0.875,-0.8125 0,-0.921875 1.1875,-1.015625 1.875,-1.015625 h 0.28125 z m 0,0"
+ id="path455"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-22"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.671875,0 V -0.6875 H 5.140625 L 3.5625,-3.140625 C 4.359375,-3.515625 4.921875,-4.25 4.921875,-5.171875 4.921875,-6.484375 3.625,-6.8125 2.625,-6.8125 H 0.265625 v 0.6875 h 0.6875 v 5.4375 h -0.6875 V 0 h 2.28125 v -0.6875 h -0.6875 V -2.90625 H 2.6875 L 4.5625,0 Z M 3.9375,-5.015625 c 0,0.875 -0.84375,1.421875 -1.59375,1.421875 H 1.859375 V -6.125 H 2.46875 c 0.65625,0 1.46875,0.21875 1.46875,1.109375 z m 0,0"
+ id="path458"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-23"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.546875,0 V -0.6875 H 5.03125 l -1.6875,-6.125 H 2.375 l -1.6875,6.125 H 0.171875 V 0 h 2.125 v -0.6875 h -0.75 c 0.171875,-0.5 0.296875,-1 0.4375,-1.515625 H 3.6875 C 3.828125,-1.6875 3.953125,-1.1875 4.125,-0.6875 H 3.375 V 0 Z m -2.0625,-2.984375 H 2.1875 C 2.40625,-3.84375 2.625,-4.703125 2.828125,-5.5625 c 0.21875,0.859375 0.4375,1.71875 0.65625,2.578125 z m 0,0"
+ id="path461"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-24"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.609375,0 V -0.6875 H 4.84375 v -2.765625 c 0,-0.96875 -0.359375,-1.6875 -1.4375,-1.6875 -0.765625,0 -1.234375,0.421875 -1.609375,1.046875 v -0.9375 H 0.125 v 0.6875 H 0.890625 V -0.6875 H 0.125 V 0 H 2.5625 V -0.6875 H 1.796875 v -2.609375 c 0.3125,-0.4375 0.71875,-0.984375 1.328125,-0.984375 0.703125,0 0.796875,0.5 0.796875,1.09375 V 0 Z m 0,0"
+ id="path464"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-25"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.359375,-7.3125 h -0.75 L 0.34375,1.359375 h 0.765625 z m 0,0"
+ id="path467"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-26"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.5,0.671875 V 0 H 0.21875 v 0.671875 z m 0,0"
+ id="path470"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph8-27"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.453125,-4.359375 V -5.03125 h -1.78125 v 0.671875 H 4.09375 L 2.90625,-1.328125 1.75,-4.359375 H 2.078125 V -5.03125 h -1.8125 v 0.671875 h 0.5625 l 1.625,4.140625 C 2,0.953125 1.90625,1.140625 0.59375,1.140625 v 0.6875 C 1.703125,1.828125 2.421875,1.75 2.875,0.625 l 2.046875,-4.984375 z m 0,0"
+ id="path473"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path476"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.359375,-4.25 0.75,-1.171875 C 0.734375,-1.09375 0.734375,-1.0625 0.703125,-0.9375 0.625,-0.625 0.609375,-0.46875 0.609375,-0.34375 c 0,0.28125 0.125,0.4375 0.328125,0.4375 0.375,0 0.765625,-0.21875 1.609375,-0.90625 L 2.71875,-0.9375 2.890625,-1.078125 2.78125,-1.28125 2.296875,-0.9375 C 1.96875,-0.71875 1.75,-0.609375 1.640625,-0.609375 c -0.109375,0 -0.15625,-0.09375 -0.15625,-0.21875 0,-0.28125 0.15625,-1.171875 0.46875,-2.75 L 2.09375,-4.25 H 3.265625 L 3.375,-4.796875 c -0.40625,0.046875 -0.78125,0.0625 -1.1875,0.0625 0.171875,-1.03125 0.28125,-1.5625 0.484375,-2.140625 l -0.125,-0.171875 c -0.21875,0.125 -0.5,0.265625 -0.84375,0.390625 l -0.28125,1.859375 c -0.46875,0.234375 -0.75,0.34375 -0.953125,0.40625 L 0.453125,-4.25 Z m 0,0"
+ id="path479"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.25,-7.046875 h 0.796875 c 0.859375,0 1.25,0.0625 1.28125,0.1875 0.03125,0.09375 0.046875,0.296875 0.046875,0.40625 l -0.046875,0.6875 H 6.625 L 6.921875,-7.546875 5.9375,-7.53125 c -0.96875,0 -1.703125,0.015625 -2.09375,0.015625 -0.390625,0 -1.09375,-0.015625 -2.03125,-0.015625 l -1.03125,-0.015625 -0.203125,1.78125 h 0.3125 L 1.0625,-6.40625 c 0.046875,-0.25 0.125,-0.421875 0.1875,-0.5 0.0625,-0.078125 0.484375,-0.140625 0.890625,-0.140625 h 1.21875 l -0.9375,5.6875 C 2.25,-0.375 2.21875,-0.34375 1.78125,-0.3125 L 1.234375,-0.265625 1.1875,0.03125 1.8125,0.015625 C 2.25,0.015625 2.5625,0 2.734375,0 2.9375,0 3.28125,0.015625 3.703125,0.015625 L 4.1875,0.03125 4.21875,-0.265625 3.578125,-0.3125 c -0.28125,0 -0.390625,-0.09375 -0.390625,-0.3125 0,-0.109375 0.015625,-0.1875 0.046875,-0.390625 z m 0,0"
+ id="path482"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.578125,-7.875 2.4375,-8 C 1.875,-7.703125 1.484375,-7.609375 0.703125,-7.53125 L 0.65625,-7.3125 h 0.515625 c 0.265625,0 0.375,0.078125 0.375,0.265625 0,0.09375 -0.015625,0.1875 -0.015625,0.265625 L 1.0625,-4.234375 c -0.296875,1.65625 -0.71875,3.53125 -0.953125,4.21875 L 0.1875,0.09375 l 0.75,-0.171875 c 0.171875,-1.25 0.359375,-1.921875 0.671875,-2.5 0.484375,-0.875 1.625,-1.9375 2.078125,-1.9375 0.140625,0 0.234375,0.09375 0.234375,0.234375 0,0.203125 -0.078125,0.609375 -0.15625,0.984375 l -0.5625,2.125 C 3.109375,-0.78125 3.0625,-0.53125 3.0625,-0.328125 c 0,0.265625 0.125,0.421875 0.328125,0.421875 0.28125,0 0.671875,-0.21875 1.75,-1.015625 L 5.03125,-1.125 4.75,-0.9375 C 4.421875,-0.734375 4.1875,-0.609375 4.078125,-0.609375 4,-0.609375 3.9375,-0.703125 3.9375,-0.828125 c 0,-0.109375 0.015625,-0.203125 0.078125,-0.4375 L 4.71875,-4.0625 c 0.0625,-0.28125 0.109375,-0.609375 0.109375,-0.796875 0,-0.25 -0.109375,-0.390625 -0.3125,-0.390625 -0.375,0 -1.03125,0.359375 -1.71875,0.9375 C 2.40625,-4 2.21875,-3.8125 1.71875,-3.15625 L 1.5,-2.890625 Z m 0,0"
+ id="path485"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.578125,-1.203125 3.3125,-1.03125 C 2.734375,-0.609375 2.21875,-0.390625 1.828125,-0.390625 1.3125,-0.390625 1,-0.796875 1,-1.453125 c 0,-0.265625 0.03125,-0.5625 0.078125,-0.875 l 0.890625,-0.21875 c 0.1875,-0.046875 0.484375,-0.15625 0.75,-0.28125 0.9375,-0.40625 1.359375,-0.90625 1.359375,-1.578125 0,-0.515625 -0.375,-0.84375 -0.921875,-0.84375 -0.703125,0 -1.90625,0.75 -2.34375,1.4375 -0.328125,0.546875 -0.65625,1.84375 -0.65625,2.578125 0,0.859375 0.484375,1.359375 1.265625,1.359375 0.625,0 1.234375,-0.3125 2.25,-1.125 z m -2.34375,-1.78125 c 0.1875,-0.75 0.40625,-1.21875 0.71875,-1.515625 0.203125,-0.171875 0.53125,-0.296875 0.796875,-0.296875 0.3125,0 0.515625,0.21875 0.515625,0.5625 0,0.484375 -0.375,1 -0.9375,1.265625 -0.3125,0.15625 -0.703125,0.28125 -1.1875,0.390625 z m 0,0"
+ id="path488"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.375,-4.234375 0.453125,-4.015625 0.796875,-4.25 c 0.40625,-0.25 0.4375,-0.265625 0.515625,-0.265625 0.109375,0 0.1875,0.109375 0.1875,0.25 0,0.078125 -0.03125,0.328125 -0.078125,0.484375 l -0.71875,2.609375 C 0.609375,-0.828125 0.5625,-0.53125 0.5625,-0.328125 0.5625,-0.0625 0.671875,0.09375 0.890625,0.09375 1.171875,0.09375 1.5625,-0.125 2.625,-0.921875 L 2.515625,-1.125 2.234375,-0.9375 c -0.3125,0.203125 -0.5625,0.328125 -0.65625,0.328125 -0.078125,0 -0.15625,-0.109375 -0.15625,-0.21875 0,-0.109375 0.03125,-0.203125 0.078125,-0.4375 l 0.84375,-3.3125 c 0.046875,-0.1875 0.0625,-0.3125 0.0625,-0.390625 0,-0.1875 -0.09375,-0.28125 -0.265625,-0.28125 -0.25,0 -0.640625,0.21875 -1.46875,0.796875 z m 2.109375,-3.53125 c -0.3125,0 -0.625,0.359375 -0.625,0.734375 0,0.265625 0.15625,0.4375 0.421875,0.4375 0.34375,0 0.59375,-0.3125 0.59375,-0.71875 0,-0.265625 -0.15625,-0.453125 -0.390625,-0.453125 z m 0,0"
+ id="path491"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.265625,-4.234375 0.34375,-4.015625 0.6875,-4.25 c 0.40625,-0.25 0.4375,-0.265625 0.515625,-0.265625 0.109375,0 0.1875,0.109375 0.1875,0.265625 0,0.5625 -0.4375,2.671875 -0.890625,4.234375 L 0.578125,0.09375 C 0.84375,0.015625 1.09375,-0.046875 1.34375,-0.09375 c 0.203125,-1.375 0.4375,-2.078125 0.9375,-2.828125 0.59375,-0.921875 1.40625,-1.59375 1.890625,-1.59375 0.125,0 0.1875,0.09375 0.1875,0.265625 0,0.1875 -0.03125,0.421875 -0.109375,0.765625 l -0.578125,2.3125 c -0.09375,0.40625 -0.140625,0.65625 -0.140625,0.828125 0,0.28125 0.125,0.4375 0.328125,0.4375 0.28125,0 0.671875,-0.21875 1.75,-1.015625 L 5.5,-1.125 5.21875,-0.9375 c -0.328125,0.203125 -0.5625,0.328125 -0.671875,0.328125 -0.078125,0 -0.140625,-0.09375 -0.140625,-0.21875 0,-0.0625 0.015625,-0.171875 0.015625,-0.21875 L 5.140625,-4.0625 c 0.078125,-0.3125 0.125,-0.609375 0.125,-0.796875 0,-0.25 -0.125,-0.390625 -0.34375,-0.390625 -0.453125,0 -1.203125,0.40625 -1.84375,1 -0.421875,0.390625 -0.71875,0.765625 -1.296875,1.5625 l 0.421875,-1.765625 c 0.046875,-0.1875 0.0625,-0.328125 0.0625,-0.4375 C 2.265625,-5.125 2.1875,-5.25 2.015625,-5.25 1.78125,-5.25 1.359375,-5.015625 0.5625,-4.453125 Z m 0,0"
+ id="path494"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.015625,-3.984375 C 4.046875,-4.390625 4.09375,-4.75 4.1875,-5.1875 4.0625,-5.25 4.03125,-5.25 3.96875,-5.25 3.625,-5.25 3.296875,-5 2.90625,-4.4375 L 2.609375,-4.015625 C 2.1875,-3.40625 2.046875,-3.171875 1.875,-2.796875 l 0.09375,-0.4375 c 0.03125,-0.25 0.125,-0.6875 0.1875,-0.9375 l 0.0625,-0.28125 c 0.046875,-0.1875 0.078125,-0.328125 0.078125,-0.453125 0,-0.21875 -0.09375,-0.34375 -0.25,-0.34375 -0.234375,0 -0.65625,0.21875 -1.453125,0.796875 l -0.3125,0.21875 0.078125,0.21875 L 0.703125,-4.25 c 0.3125,-0.1875 0.4375,-0.25 0.53125,-0.25 0.109375,0 0.1875,0.109375 0.1875,0.25 0,0.625 -0.46875,2.875 -0.90625,4.265625 L 0.625,0.09375 C 0.78125,0.046875 0.953125,0.015625 1.203125,-0.046875 L 1.359375,-0.0625 1.640625,-1.375 c 0.1875,-0.90625 0.4375,-1.484375 0.921875,-2.109375 0.375,-0.46875 0.671875,-0.703125 0.90625,-0.703125 0.15625,0 0.265625,0.046875 0.390625,0.203125 z m 0,0"
+ id="path497"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-8"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 4.390625,-5.140625 4.28125,-5.25 3.921875,-5.046875 C 3.46875,-5.21875 3.28125,-5.25 2.984375,-5.25 c -0.296875,0 -0.515625,0.046875 -0.8125,0.1875 -0.671875,0.34375 -1.03125,0.671875 -1.3125,1.203125 -0.484375,0.96875 -0.8125,2.28125 -0.8125,3.125 0,0.484375 0.15625,0.859375 0.375,0.859375 0.234375,0 0.640625,-0.25 1.0625,-0.609375 0.453125,-0.421875 0.875,-0.90625 1.46875,-1.734375 l -0.3125,1.375 c -0.046875,0.1875 -0.0625,0.390625 -0.0625,0.5625 0,0.234375 0.09375,0.375 0.25,0.375 0.265625,0 0.703125,-0.28125 1.59375,-1.015625 l -0.0625,-0.234375 c -0.078125,0.0625 -0.109375,0.078125 -0.15625,0.125 -0.34375,0.296875 -0.5,0.390625 -0.671875,0.390625 -0.09375,0 -0.15625,-0.09375 -0.15625,-0.25 0,-0.0625 0,-0.09375 0,-0.125 z m -0.90625,0.625 c -0.25,1.1875 -0.453125,1.75 -0.828125,2.328125 -0.609375,0.90625 -1.28125,1.546875 -1.625,1.546875 -0.140625,0 -0.203125,-0.140625 -0.203125,-0.4375 0,-0.703125 0.3125,-1.96875 0.6875,-2.84375 0.265625,-0.609375 0.515625,-0.796875 1.03125,-0.796875 0.25,0 0.453125,0.046875 0.9375,0.203125 z m 0,0"
+ id="path500"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-9"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.734375,-7.875 2.609375,-8 c -0.5625,0.296875 -0.96875,0.390625 -1.75,0.46875 L 0.8125,-7.3125 h 0.53125 c 0.265625,0 0.375,0.078125 0.375,0.25 0,0.03125 0,0.078125 -0.046875,0.28125 l -0.03125,0.234375 C 1.578125,-5.9375 0.921875,-2.546875 0.75,-2 l -0.15625,0.5625 c -0.140625,0.546875 -0.203125,0.875 -0.203125,1.09375 0,0.28125 0.125,0.4375 0.328125,0.4375 0.28125,0 0.671875,-0.21875 1.75,-1.015625 L 2.359375,-1.125 2.078125,-0.9375 C 1.75,-0.734375 1.515625,-0.609375 1.40625,-0.609375 c -0.078125,0 -0.140625,-0.109375 -0.140625,-0.21875 0,-0.0625 0.015625,-0.140625 0.046875,-0.3125 l 0.015625,-0.09375 z m 0,0"
+ id="path503"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-10"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.125,-4.171875 c 0.03125,-0.21875 0.109375,-0.46875 0.171875,-0.609375 L 3.265625,-4.859375 3.1875,-4.84375 c -0.265625,0.0625 -0.390625,0.078125 -0.921875,0.078125 H 2.09375 l 0.234375,-1.21875 C 2.5,-6.921875 2.796875,-7.34375 3.296875,-7.34375 c 0.328125,0 0.625,0.171875 0.796875,0.421875 l 0.109375,-0.03125 C 4.25,-7.125 4.359375,-7.46875 4.453125,-7.6875 L 4.5,-7.859375 C 4.328125,-7.921875 3.984375,-8 3.734375,-8 3.625,-8 3.453125,-7.96875 3.359375,-7.921875 3.09375,-7.796875 2.203125,-7.125 1.953125,-6.875 c -0.234375,0.25 -0.375,0.578125 -0.484375,1.1875 l -0.171875,0.859375 c -0.453125,0.21875 -0.671875,0.3125 -0.9375,0.40625 l -0.046875,0.25 h 0.875 L 1.09375,-3.5625 C 0.765625,-1.4375 0.359375,0.59375 0.125,1.34375 c -0.203125,0.640625 -0.53125,0.984375 -0.921875,0.984375 -0.25,0 -0.375,-0.078125 -0.5625,-0.328125 l -0.15625,0.046875 c -0.046875,0.25 -0.203125,0.78125 -0.25,0.875 0.09375,0.0625 0.265625,0.09375 0.375,0.09375 0.453125,0 1.046875,-0.34375 1.46875,-0.859375 0.65625,-0.78125 0.90625,-1.546875 1.703125,-5.375 0.03125,-0.125 0.109375,-0.546875 0.203125,-0.953125 z m 0,0"
+ id="path506"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-11"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.03125,-5.25 c -0.46875,0 -0.984375,0.171875 -1.46875,0.53125 -0.890625,0.625 -1.375,1.734375 -1.375,3.0625 0,1.15625 0.484375,1.78125 1.390625,1.78125 0.609375,0 1.25,-0.28125 1.75,-0.75 C 4,-1.265625 4.484375,-2.515625 4.484375,-3.609375 4.484375,-4.640625 3.9375,-5.25 3.03125,-5.25 Z M 2.625,-4.84375 c 0.671875,0 1.03125,0.484375 1.03125,1.40625 0,1.046875 -0.34375,2.203125 -0.828125,2.78125 -0.1875,0.234375 -0.46875,0.359375 -0.8125,0.359375 -0.625,0 -1,-0.484375 -1,-1.34375 0,-1.234375 0.421875,-2.578125 0.953125,-3.015625 0.140625,-0.125 0.390625,-0.1875 0.65625,-0.1875 z m 0,0"
+ id="path509"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-12"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.734375,-3.59375 h 0.25 C 4.0625,-4.3125 4.140625,-4.71875 4.25,-5 3.984375,-5.15625 3.59375,-5.25 3.203125,-5.25 c -0.5,0 -1.3125,0.390625 -1.921875,0.9375 -0.59375,0.53125 -1.015625,1.6875 -1.015625,2.828125 0,1.046875 0.46875,1.609375 1.34375,1.609375 0.578125,0 1.109375,-0.21875 1.703125,-0.71875 L 3.859375,-1.03125 3.78125,-1.25 3.609375,-1.140625 C 2.828125,-0.625 2.40625,-0.4375 2.03125,-0.4375 c -0.609375,0 -0.9375,-0.4375 -0.9375,-1.296875 0,-1.171875 0.390625,-2.3125 0.921875,-2.71875 0.234375,-0.1875 0.5,-0.265625 0.828125,-0.265625 0.5,0 0.890625,0.203125 0.890625,0.46875 z m 0,0"
+ id="path512"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-13"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.34375,-1.609375 c -0.0625,0.546875 -0.125,0.9375 -0.25,1.4375 0.421875,0.1875 0.796875,0.296875 1.171875,0.296875 0.53125,0 1.03125,-0.203125 1.59375,-0.640625 0.546875,-0.4375 0.78125,-0.84375 0.78125,-1.375 0,-0.59375 -0.34375,-0.90625 -1.15625,-1.0625 l -0.46875,-0.09375 c -0.65625,-0.109375 -0.859375,-0.296875 -0.859375,-0.75 0,-0.578125 0.484375,-1.03125 1.109375,-1.03125 0.453125,0 0.859375,0.203125 1.03125,0.5 v 0.59375 H 3.5625 C 3.59375,-4.109375 3.640625,-4.40625 3.765625,-4.96875 3.34375,-5.171875 3.03125,-5.25 2.671875,-5.25 c -0.5625,0 -1.234375,0.328125 -1.75,0.84375 -0.296875,0.296875 -0.40625,0.5625 -0.40625,0.953125 0,0.625 0.328125,0.96875 1.0625,1.109375 L 2.25,-2.21875 C 2.734375,-2.125 2.90625,-1.9375 2.90625,-1.5 c 0,0.703125 -0.5,1.1875 -1.265625,1.1875 -0.390625,0 -0.71875,-0.125 -1.03125,-0.390625 v -0.90625 z m 0,0"
+ id="path515"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-14"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 7.96875,-1.125 -0.296875,0.1875 c -0.3125,0.203125 -0.546875,0.328125 -0.65625,0.328125 -0.078125,0 -0.140625,-0.09375 -0.140625,-0.21875 0,-0.109375 0.015625,-0.203125 0.078125,-0.4375 L 7.765625,-4.5 C 7.8125,-4.6875 7.84375,-4.859375 7.84375,-4.953125 7.84375,-5.140625 7.734375,-5.25 7.5625,-5.25 c -0.328125,0 -0.734375,0.1875 -1.40625,0.65625 -0.6875,0.5 -1.0625,0.875 -1.59375,1.625 L 4.890625,-4.453125 C 4.921875,-4.671875 4.96875,-4.84375 4.96875,-4.921875 4.96875,-5.125 4.859375,-5.25 4.671875,-5.25 4.359375,-5.25 3.84375,-5.015625 3.25,-4.5625 2.765625,-4.1875 2.546875,-3.953125 1.84375,-3 L 2.203125,-4.453125 C 2.25,-4.625 2.265625,-4.78125 2.265625,-4.921875 2.265625,-5.125 2.171875,-5.25 2.015625,-5.25 1.78125,-5.25 1.375,-5.03125 0.5625,-4.453125 L 0.265625,-4.234375 0.34375,-4.015625 0.6875,-4.25 c 0.40625,-0.25 0.4375,-0.265625 0.515625,-0.265625 0.109375,0 0.1875,0.109375 0.1875,0.265625 0,0.5625 -0.4375,2.671875 -0.890625,4.234375 l 0.03125,0.109375 0.75,-0.15625 0.234375,-1.109375 c 0.265625,-1.21875 0.5625,-1.859375 1.15625,-2.515625 0.453125,-0.5 0.953125,-0.828125 1.25,-0.828125 0.078125,0 0.125,0.09375 0.125,0.234375 0,0.375 -0.234375,1.625 -0.6875,3.53125 L 3.1875,-0.015625 3.234375,0.09375 3.984375,-0.0625 4.21875,-1.234375 C 4.390625,-2.109375 4.765625,-2.9375 5.25,-3.46875 c 0.59375,-0.671875 1.140625,-1.046875 1.484375,-1.046875 0.09375,0 0.140625,0.09375 0.140625,0.265625 0,0.265625 -0.03125,0.421875 -0.265625,1.375 C 6.4375,-2.1875 6.25,-1.53125 6.140625,-1.171875 6.046875,-0.859375 6,-0.578125 6,-0.34375 c 0,0.28125 0.125,0.4375 0.328125,0.4375 0.28125,0 0.671875,-0.21875 1.75,-1.015625 z m 0,0"
+ id="path518"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-15"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.25,-0.03125 1.359375,0 c 0.28125,0.09375 0.4375,0.125 0.5625,0.125 0.609375,0 1.859375,-0.796875 2.328125,-1.484375 0.453125,-0.671875 0.828125,-1.875 0.828125,-2.6875 0,-0.734375 -0.25,-1.203125 -0.65625,-1.203125 -0.453125,0 -1.03125,0.28125 -1.59375,0.796875 -0.453125,0.375 -0.671875,0.65625 -1.0625,1.296875 L 2.03125,-4.453125 c 0.03125,-0.1875 0.046875,-0.34375 0.046875,-0.46875 C 2.078125,-5.140625 2,-5.25 1.84375,-5.25 c -0.234375,0 -0.640625,0.21875 -1.453125,0.796875 l -0.296875,0.21875 0.0625,0.21875 L 0.515625,-4.25 C 0.8125,-4.4375 0.9375,-4.5 1.03125,-4.5 c 0.109375,0 0.1875,0.109375 0.1875,0.25 0,0.09375 -0.015625,0.3125 -0.046875,0.421875 l -0.625,3.734375 C 0.4375,0.5625 0.234375,1.5625 0.015625,2.546875 L -0.078125,2.9375 0,3.015625 C 0.234375,2.9375 0.453125,2.875 0.796875,2.828125 Z M 1.5625,-1.796875 C 1.796875,-3.203125 2.96875,-4.625 3.875,-4.625 c 0.28125,0 0.40625,0.234375 0.40625,0.75 0,0.875 -0.4375,2.171875 -1.015625,3 -0.21875,0.3125 -0.5625,0.484375 -1.015625,0.484375 -0.328125,0 -0.609375,-0.078125 -0.890625,-0.25 z m 0,0"
+ id="path521"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-16"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.625,-1.0625 C 3.5625,-0.796875 3.515625,-0.5 3.515625,-0.34375 c 0,0.28125 0.109375,0.4375 0.328125,0.4375 0.28125,0 0.671875,-0.21875 1.734375,-1.015625 L 5.46875,-1.125 5.1875,-0.9375 c -0.265625,0.171875 -0.546875,0.296875 -0.65625,0.296875 -0.09375,0 -0.140625,-0.078125 -0.140625,-0.1875 0,-0.09375 0.015625,-0.203125 0.046875,-0.375 l 0.015625,-0.0625 c 0.25,-1.1875 0.578125,-2.640625 0.90625,-3.890625 l -0.0625,-0.09375 -0.75,0.171875 -0.109375,0.5625 C 4.28125,-3.671875 4,-2.921875 3.671875,-2.40625 c -0.65625,0.984375 -1.5,1.765625 -1.9375,1.765625 -0.09375,0 -0.140625,-0.09375 -0.140625,-0.28125 0,-0.15625 0.015625,-0.296875 0.078125,-0.578125 l 0.625,-2.953125 C 2.328125,-4.625 2.34375,-4.78125 2.34375,-4.921875 2.34375,-5.125 2.25,-5.25 2.09375,-5.25 c -0.21875,0 -0.625,0.21875 -1.4375,0.796875 l -0.3125,0.21875 0.078125,0.21875 L 0.78125,-4.25 c 0.296875,-0.1875 0.421875,-0.25 0.515625,-0.25 0.09375,0 0.1875,0.109375 0.1875,0.21875 0,0.046875 -0.015625,0.15625 -0.015625,0.203125 L 0.78125,-0.84375 C 0.75,-0.734375 0.734375,-0.484375 0.734375,-0.328125 c 0,0.25 0.15625,0.453125 0.375,0.453125 0.6875,0 2.015625,-1.21875 2.921875,-2.734375 z m 0,0"
+ id="path524"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-17"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 5.265625,-7.875 5.140625,-8 c -0.578125,0.296875 -0.96875,0.390625 -1.75,0.46875 L 3.34375,-7.3125 H 3.875 c 0.265625,0 0.375,0.078125 0.375,0.265625 0,0.09375 -0.015625,0.1875 -0.03125,0.265625 L 3.921875,-5.109375 C 3.59375,-5.203125 3.296875,-5.25 3.015625,-5.25 c -0.75,0 -1.765625,0.78125 -2.28125,1.734375 -0.328125,0.625 -0.546875,1.65625 -0.546875,2.578125 0,0.703125 0.15625,1.0625 0.484375,1.0625 0.28125,0 0.6875,-0.1875 1.0625,-0.484375 0.59375,-0.484375 0.953125,-0.90625 1.671875,-2 l -0.25,0.984375 c -0.109375,0.484375 -0.171875,0.828125 -0.171875,1.109375 0,0.234375 0.109375,0.359375 0.28125,0.359375 0.1875,0 0.453125,-0.125 0.828125,-0.40625 l 0.875,-0.640625 -0.109375,-0.21875 -0.46875,0.34375 c -0.15625,0.109375 -0.328125,0.1875 -0.4375,0.1875 -0.078125,0 -0.140625,-0.09375 -0.140625,-0.25 0,-0.09375 0,-0.1875 0.078125,-0.5 z m -1.59375,4.046875 c -0.1875,0.953125 -0.734375,1.921875 -1.40625,2.5625 -0.375,0.359375 -0.8125,0.625 -1.015625,0.625 -0.1875,0 -0.28125,-0.15625 -0.28125,-0.421875 0,-1.375 0.5,-3.078125 1.03125,-3.5 0.15625,-0.109375 0.359375,-0.15625 0.65625,-0.15625 0.46875,0 0.796875,0.0625 1.15625,0.25 z m 0,0"
+ id="path527"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-18"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.5625,-7.875 2.4375,-8 c -0.578125,0.296875 -0.96875,0.390625 -1.75,0.46875 L 0.640625,-7.3125 h 0.53125 c 0.25,0 0.359375,0.078125 0.359375,0.265625 0,0.078125 0,0.203125 -0.015625,0.265625 l -1.09375,6 C 0.40625,-0.734375 0.40625,-0.703125 0.40625,-0.671875 c 0,0.4375 0.515625,0.796875 1.125,0.796875 0.40625,0 0.953125,-0.21875 1.421875,-0.546875 C 4,-1.171875 4.71875,-2.65625 4.71875,-4.09375 4.71875,-4.515625 4.625,-4.9375 4.5,-5.109375 4.421875,-5.203125 4.28125,-5.25 4.109375,-5.25 c -0.265625,0 -0.59375,0.078125 -0.890625,0.234375 -0.5625,0.296875 -0.921875,0.625 -1.59375,1.484375 z m 0.953125,3.25 c 0.28125,0 0.421875,0.25 0.421875,0.78125 0,0.703125 -0.234375,1.640625 -0.5625,2.34375 -0.359375,0.765625 -0.796875,1.109375 -1.375,1.109375 -0.5,0 -0.78125,-0.25 -0.78125,-0.703125 0,-0.28125 0.046875,-0.578125 0.140625,-0.984375 0.21875,-0.875 0.46875,-1.40625 0.90625,-1.859375 0.359375,-0.375 0.9375,-0.6875 1.25,-0.6875 z m 0,0"
+ id="path530"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-19"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.625,-4.609375 3.734375,-4.40625 C 3.84375,-4.46875 3.9375,-4.5 4.03125,-4.5 4.328125,-4.5 4.5,-4.25 4.5,-3.8125 c 0,1.609375 -1.046875,3.390625 -2.015625,3.390625 -0.53125,0 -0.875,-0.46875 -0.875,-1.171875 0,-1.140625 0.4375,-2.140625 1.5,-3.46875 L 3,-5.25 c -0.21875,0.09375 -0.359375,0.125 -0.671875,0.125 -0.296875,0 -0.75,-0.015625 -1.078125,-0.0625 H 1.125 C 1.0625,-5.203125 1,-5.203125 1,-5.203125 0.859375,-5.203125 0.765625,-5.1875 0.640625,-5.125 0.484375,-4.828125 0.375,-4.4375 0.234375,-3.84375 H 0.46875 l 0.1875,-0.453125 c 0.078125,-0.1875 0.296875,-0.3125 0.546875,-0.3125 0.0625,0 0.15625,0 0.296875,0.015625 0.09375,0.015625 0.171875,0.015625 0.3125,0.015625 0.234375,0 0.40625,-0.015625 0.6875,-0.046875 -1.21875,1.3125 -1.671875,2.21875 -1.671875,3.3125 0,0.828125 0.5,1.4375 1.203125,1.4375 0.453125,0 0.875,-0.203125 1.375,-0.65625 C 3.921875,-1 4.4375,-1.71875 4.78125,-2.46875 5.015625,-3.015625 5.203125,-3.75 5.203125,-4.1875 c 0,-0.625 -0.28125,-1.0625 -0.671875,-1.0625 -0.140625,0 -0.28125,0.03125 -0.359375,0.125 z m 0,0"
+ id="path533"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-20"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 6.046875,-4.609375 6.15625,-4.40625 C 6.265625,-4.46875 6.359375,-4.5 6.453125,-4.5 c 0.296875,0 0.46875,0.25 0.46875,0.6875 0,1.578125 -1.046875,3.390625 -1.984375,3.390625 -0.3125,0 -0.546875,-0.4375 -0.546875,-1.046875 0,-0.5 0.109375,-1.21875 0.234375,-1.6875 L 5.1875,-5.171875 5.109375,-5.25 4.3125,-5.015625 l -0.328125,1.625 c -0.125,0.671875 -0.28125,1.109375 -0.59375,1.703125 -0.4375,0.8125 -0.84375,1.265625 -1.171875,1.265625 -0.390625,0 -0.640625,-0.421875 -0.640625,-1.0625 0,-1.296875 0.453125,-2.359375 1.53125,-3.578125 L 3,-5.25 c -0.21875,0.09375 -0.359375,0.125 -0.671875,0.125 -0.296875,0 -0.75,-0.015625 -1.078125,-0.0625 H 1.125 C 1.0625,-5.203125 1,-5.203125 1,-5.203125 0.859375,-5.203125 0.765625,-5.1875 0.640625,-5.125 0.484375,-4.828125 0.375,-4.4375 0.234375,-3.84375 H 0.46875 l 0.1875,-0.453125 c 0.078125,-0.1875 0.296875,-0.3125 0.546875,-0.3125 0.0625,0 0.15625,0 0.296875,0.015625 0.09375,0.015625 0.171875,0.015625 0.328125,0.015625 0.21875,0 0.359375,-0.015625 0.640625,-0.046875 L 2.4375,-4.578125 C 2.359375,-4.5 2.328125,-4.4375 2.140625,-4.234375 1.15625,-3.09375 0.78125,-2.296875 0.78125,-1.375 c 0,0.890625 0.390625,1.5 0.96875,1.5 0.6875,0 1.265625,-0.609375 2.0625,-2.171875 C 3.71875,-1.5625 3.6875,-1.28125 3.6875,-1.03125 3.6875,-0.34375 4,0.125 4.5,0.125 5.375,0.125 6.515625,-0.984375 7.203125,-2.46875 7.4375,-3.015625 7.625,-3.75 7.625,-4.1875 7.625,-4.8125 7.34375,-5.25 6.953125,-5.25 6.8125,-5.25 6.671875,-5.21875 6.59375,-5.125 Z m 0,0"
+ id="path536"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-21"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.234375,-1.21875 c -0.359375,0 -0.65625,0.34375 -0.65625,0.765625 0,0.3125 0.1875,0.5 0.484375,0.5 0.359375,0 0.65625,-0.34375 0.65625,-0.75 C 1.71875,-1 1.5,-1.21875 1.234375,-1.21875 Z m 0,0"
+ id="path539"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-22"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.234375,-0.953125 c 0,0.21875 -0.03125,0.359375 -0.09375,0.703125 C 0.125,-0.125 0.109375,-0.09375 0.09375,-0.015625 0.265625,0.078125 0.4375,0.125 0.5625,0.125 c 0.359375,0 0.796875,-0.328125 1.125,-0.828125 l 0.828125,-1.28125 0.125,0.75 C 2.78125,-0.3125 3.03125,0.125 3.421875,0.125 c 0.25,0 0.59375,-0.1875 0.9375,-0.5 L 4.890625,-0.859375 4.796875,-1.0625 c -0.390625,0.328125 -0.65625,0.484375 -0.84375,0.484375 -0.15625,0 -0.296875,-0.109375 -0.40625,-0.328125 -0.09375,-0.203125 -0.21875,-0.609375 -0.28125,-0.921875 l -0.1875,-1.109375 0.375,-0.53125 c 0.515625,-0.703125 0.8125,-0.953125 1.15625,-0.953125 0.171875,0 0.296875,0.078125 0.359375,0.25 L 5.109375,-4.21875 5.28125,-5.140625 C 5.140625,-5.21875 5.046875,-5.25 4.953125,-5.25 c -0.4375,0 -0.875,0.390625 -1.546875,1.390625 L 3,-3.265625 2.9375,-3.78125 C 2.796875,-4.859375 2.515625,-5.25 1.859375,-5.25 1.578125,-5.25 1.34375,-5.171875 1.25,-5.03125 l -0.640625,0.90625 0.1875,0.109375 c 0.328125,-0.375 0.546875,-0.515625 0.75,-0.515625 0.359375,0 0.609375,0.4375 0.78125,1.515625 l 0.125,0.671875 -0.4375,0.671875 C 1.546875,-0.9375 1.171875,-0.59375 0.875,-0.59375 0.703125,-0.59375 0.59375,-0.625 0.5625,-0.6875 L 0.453125,-1 Z m 0,0"
+ id="path542"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-23"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.03125,-7.6875 -4.0625,6.46875 C 0.578125,-0.609375 0.375,-0.4375 0.015625,-0.34375 l -0.21875,0.046875 V 0.03125 C 0.796875,0 0.796875,0 1.015625,0 1.21875,0 1.25,0 2.1875,0.03125 V -0.265625 L 1.609375,-0.3125 c -0.171875,0 -0.328125,-0.109375 -0.328125,-0.203125 0,-0.078125 0.078125,-0.234375 0.28125,-0.59375 l 1.109375,-1.90625 h 2.6875 L 5.625,-0.96875 v 0.03125 c 0,0.015625 0.015625,0.046875 0.03125,0.09375 0,0.09375 0.015625,0.203125 0.015625,0.25 0,0.171875 -0.171875,0.265625 -0.46875,0.28125 L 4.71875,-0.265625 V 0.03125 C 5.828125,0 5.828125,0 6.046875,0 c 0.21875,0 0.21875,0 1.34375,0.03125 V -0.265625 L 7.09375,-0.3125 C 6.59375,-0.375 6.578125,-0.375 6.484375,-0.875 l -0.9375,-6.8125 z m -0.140625,1.140625 0.40625,3.140625 H 2.9375 Z m 0,0"
+ id="path545"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph9-24"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.8125,-7.234375 0.03125,-0.3125 H 3.578125 l -0.984375,0.03125 c -0.171875,0 -0.375,0 -0.84375,-0.015625 l -0.6875,-0.015625 -0.03125,0.3125 0.5,0.015625 c 0.265625,0.015625 0.390625,0.09375 0.390625,0.296875 0,0.15625 -0.046875,0.484375 -0.09375,0.828125 l -0.9375,5.5 C 0.84375,-0.40625 0.703125,-0.328125 0.234375,-0.25 L 0.171875,0.03125 0.625,0.015625 C 0.953125,0.015625 1.640625,0 1.859375,0 l 2.34375,0.03125 H 4.3125 c 0.140625,0 0.421875,-0.015625 0.78125,-0.015625 L 5.453125,0 C 5.4375,-0.265625 5.5625,-1.125 5.703125,-1.796875 H 5.359375 L 5.1875,-1.125 C 5.078125,-0.78125 4.984375,-0.59375 4.890625,-0.53125 4.75,-0.484375 4.046875,-0.421875 3.3125,-0.421875 2.78125,-0.421875 2.484375,-0.4375 1.765625,-0.5 v -0.046875 c 0,-0.15625 0.015625,-0.234375 0.015625,-0.34375 L 2.796875,-6.6875 C 2.875,-7.09375 2.9375,-7.171875 3.34375,-7.203125 Z m 0,0"
+ id="path548"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path551"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.828125,-7.3125 c -0.40625,0 -0.734375,0.328125 -0.734375,0.71875 0,0.40625 0.328125,0.734375 0.734375,0.734375 0.390625,0 0.71875,-0.328125 0.71875,-0.734375 0,-0.390625 -0.328125,-0.71875 -0.71875,-0.71875 z m 0,0"
+ id="path554"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3,-7.3125 c -0.421875,0 -0.75,0.328125 -0.75,0.71875 0,0.40625 0.328125,0.734375 0.734375,0.734375 0.40625,0 0.734375,-0.328125 0.734375,-0.734375 C 3.71875,-6.984375 3.390625,-7.3125 3,-7.3125 Z m -2.34375,0 c -0.421875,0 -0.75,0.328125 -0.75,0.71875 0,0.40625 0.328125,0.734375 0.734375,0.734375 0.40625,0 0.734375,-0.328125 0.734375,-0.734375 0,-0.390625 -0.328125,-0.71875 -0.71875,-0.71875 z m 0,0"
+ id="path557"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.6875,-7.390625 H 1.46875 C 1.359375,-7.390625 1,-7.40625 0.375,-7.421875 v 0.390625 l 0.40625,0.046875 c 0.5,0.03125 0.53125,0.109375 0.53125,1.0625 v 4.453125 c 0,0.953125 -0.03125,1.015625 -0.53125,1.0625 L 0.375,-0.375 V 0.03125 C 1.421875,0 1.421875,0 1.640625,0 1.859375,0 2.359375,0.015625 2.875,0.03125 V -0.375 L 2.46875,-0.40625 C 1.984375,-0.453125 1.953125,-0.5 1.953125,-1.46875 V -5.765625 L 5.5,-1.484375 c 0.296875,0.34375 0.5625,0.65625 1.34375,1.515625 L 7.734375,0.171875 7.8125,0.125 C 7.78125,-0.484375 7.78125,-0.71875 7.78125,-0.96875 v -4.953125 c 0,-0.953125 0.03125,-1.03125 0.515625,-1.0625 l 0.40625,-0.046875 v -0.390625 l -1.25,0.03125 c -0.109375,0 -0.28125,0 -1.25,-0.03125 v 0.390625 l 0.40625,0.046875 C 7.09375,-6.953125 7.125,-6.875 7.125,-5.921875 V -2 L 3.734375,-5.984375 C 3.5,-6.234375 3.296875,-6.5 2.609375,-7.421875 Z m 0,0"
+ id="path560"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.125,-5.140625 c -1.734375,0 -2.6875,0.96875 -2.6875,2.703125 0,1.671875 0.890625,2.625 2.46875,2.625 1.75,0 2.734375,-1 2.734375,-2.765625 0,-1.65625 -0.890625,-2.5625 -2.515625,-2.5625 z M 3,-4.609375 c 0.78125,0 1.15625,0.765625 1.15625,2.375 0,1.328125 -0.3125,1.890625 -1.046875,1.890625 -0.78125,0 -1.1875,-0.796875 -1.1875,-2.359375 C 1.921875,-4.03125 2.25,-4.609375 3,-4.609375 Z m 0,0"
+ id="path563"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.53125,-0.65625 3.453125,-0.859375 C 3.234375,-0.75 3.125,-0.71875 2.9375,-0.71875 c -0.5,0 -0.671875,-0.171875 -0.671875,-0.703125 V -4.03125 h 1.15625 l 0.09375,-0.703125 -1.25,0.0625 v -0.625 c 0,-0.578125 0.03125,-0.9375 0.140625,-1.484375 L 2.25,-6.890625 c -0.4375,0.203125 -0.78125,0.34375 -1.328125,0.546875 0.03125,0.5625 0.03125,0.765625 0.03125,1 v 0.65625 l -0.71875,0.46875 v 0.234375 L 0.9375,-4.03125 v 2.828125 c 0,0.96875 0.40625,1.390625 1.359375,1.390625 C 2.625,0.1875 2.90625,0.109375 3,-0.015625 Z m 0,0"
+ id="path566"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-6"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 5.03125,-3.21875 c 0,-1.171875 -0.828125,-1.921875 -2.0625,-1.921875 -0.390625,0 -0.671875,0.078125 -0.96875,0.25 l -0.5,0.3125 C 0.78125,-4.15625 0.453125,-3.5 0.453125,-2.46875 c 0,1.734375 0.875,2.65625 2.5,2.65625 0.625,0 1.03125,-0.109375 1.71875,-0.46875 l 0.25,-0.53125 -0.140625,-0.15625 c -0.5,0.28125 -0.828125,0.375 -1.265625,0.375 -0.578125,0 -1.109375,-0.296875 -1.375,-0.765625 -0.171875,-0.3125 -0.25,-0.5625 -0.265625,-1.078125 h 1.421875 c 0.625,0 1.125,-0.0625 1.734375,-0.21875 z m -2.3125,0.234375 H 2.6875 c -0.0625,0 -0.359375,0 -0.53125,-0.015625 L 1.8125,-3.015625 C 1.84375,-4.09375 2.109375,-4.53125 2.734375,-4.53125 c 0.625,0 0.890625,0.4375 0.90625,1.515625 z m 0,0"
+ id="path569"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph10-7"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 1.375,-1.578125 c -0.453125,0 -0.859375,0.40625 -0.859375,0.875 0,0.453125 0.390625,0.828125 0.84375,0.828125 0.453125,0 0.859375,-0.390625 0.859375,-0.828125 0,-0.453125 -0.40625,-0.875 -0.84375,-0.875 z m 0,-3.375 c -0.453125,0 -0.859375,0.40625 -0.859375,0.859375 0,0.46875 0.390625,0.84375 0.84375,0.84375 0.453125,0 0.859375,-0.390625 0.859375,-0.84375 0,-0.4375 -0.40625,-0.859375 -0.84375,-0.859375 z m 0,0"
+ id="path572"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph11-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path575"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph11-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.234375,-3.984375 0.140625,0.28125 0.40625,-0.21875 c 0.109375,-0.0625 0.25,-0.109375 0.359375,-0.109375 0.109375,0 0.171875,0.0625 0.171875,0.171875 0,0.234375 -0.109375,0.78125 -0.359375,1.75 -0.046875,0.171875 -0.109375,0.375 -0.171875,0.625 v 0.0625 L 0.71875,-1.25 c -0.09375,0.40625 -0.140625,0.625 -0.140625,0.8125 0,0.375 0.203125,0.625 0.484375,0.625 0.765625,0 1.78125,-0.921875 2.859375,-2.625 l -0.34375,1.265625 c -0.125,0.4375 -0.171875,0.71875 -0.171875,0.890625 0,0.265625 0.15625,0.46875 0.375,0.46875 0.21875,0 0.875,-0.375 1.515625,-0.859375 0.0625,-0.046875 0.25,-0.1875 0.390625,-0.28125 l -0.109375,-0.3125 -0.25,0.1875 c -0.21875,0.15625 -0.4375,0.265625 -0.59375,0.265625 -0.09375,0 -0.15625,-0.046875 -0.15625,-0.125 0,-0.140625 0.0625,-0.421875 0.171875,-0.78125 0,-0.03125 0,-0.078125 0.03125,-0.140625 0,-0.03125 0.25,-0.96875 0.390625,-1.546875 0.09375,-0.359375 0.1875,-0.671875 0.453125,-1.546875 l -0.09375,-0.125 C 5.0625,-4.921875 4.6875,-4.859375 4.328125,-4.875 4.3125,-4.0625 3.984375,-3.046875 3.453125,-2.203125 2.9375,-1.359375 2.34375,-0.78125 2.03125,-0.78125 c -0.09375,0 -0.171875,-0.0625 -0.171875,-0.140625 0,-0.171875 0.03125,-0.4375 0.109375,-0.71875 L 2.34375,-3.125 c 0.28125,-1.078125 0.3125,-1.296875 0.3125,-1.609375 0,-0.234375 -0.109375,-0.375 -0.296875,-0.375 -0.28125,0 -0.765625,0.203125 -1.265625,0.546875 z m 0,0"
+ id="path578"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph11-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.0625,0.1875 h 0.265625 c 0.5,-0.890625 0.640625,-1.125 0.78125,-1.359375 L 8.28125,-6.390625 7.390625,-1.09375 c 0,0.015625 -0.015625,0.0625 -0.03125,0.109375 -0.015625,0.0625 -0.015625,0.09375 -0.015625,0.09375 C 7.265625,-0.484375 7.21875,-0.4375 6.875,-0.375 l -0.53125,0.03125 -0.046875,0.375 C 7.71875,0 7.71875,0 7.984375,0 8.25,0 8.25,0 9.640625,0.03125 l 0.0625,-0.375 L 9.09375,-0.375 C 8.8125,-0.390625 8.703125,-0.484375 8.703125,-0.703125 8.703125,-0.78125 8.71875,-0.90625 8.75,-1.109375 8.765625,-1.15625 8.78125,-1.1875 8.78125,-1.203125 l 0.875,-5.09375 c 0.109375,-0.578125 0.203125,-0.71875 0.609375,-0.75 l 0.421875,-0.03125 0.0625,-0.34375 c -1.046875,0.03125 -1.046875,0.03125 -1.25,0.03125 -0.203125,0 -0.71875,-0.015625 -1.234375,-0.03125 -0.859375,1.546875 -1.5,2.609375 -3.359375,5.53125 l -1.390625,-5.53125 c -1,0.03125 -1,0.03125 -1.203125,0.03125 -0.203125,0 -0.703125,-0.015625 -1.203125,-0.03125 l -0.046875,0.34375 0.484375,0.03125 c 0.40625,0.015625 0.578125,0.125 0.578125,0.359375 0,0.203125 -0.03125,0.421875 -0.09375,0.671875 L 0.671875,-1 c -0.109375,0.40625 -0.25,0.59375 -0.4375,0.625 L -0.234375,-0.34375 -0.25,0.03125 C 0.734375,0 0.734375,0 0.9375,0 1.140625,0 1.625,0.015625 2.109375,0.03125 l 0.0625,-0.375 -0.5625,-0.03125 C 1.34375,-0.390625 1.25,-0.484375 1.25,-0.703125 c 0,-0.109375 0,-0.125 0.078125,-0.46875 L 2.5,-5.984375 Z m 0,0"
+ id="path581"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph11-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 6.78125,-5.28125 h 0.390625 c 0.046875,-0.515625 0.125,-0.828125 0.40625,-1.828125 C 6.875,-7.4375 6.25,-7.578125 5.5,-7.578125 c -2.625,0 -4.75,2.15625 -4.75,4.859375 0,1.046875 0.3125,1.796875 0.90625,2.296875 C 2.140625,-0.03125 2.875,0.1875 3.703125,0.1875 c 1.03125,0 1.8125,-0.28125 3.015625,-1.03125 L 6.859375,-1.265625 6.75,-1.359375 6.515625,-1.21875 c -0.828125,0.484375 -1.484375,0.6875 -2.15625,0.6875 -1.4375,0 -2.109375,-0.765625 -2.109375,-2.4375 0,-2.421875 1.046875,-3.96875 2.671875,-3.96875 1.015625,0 1.9375,0.34375 1.921875,0.703125 z m 0,0"
+ id="path584"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph11-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.953125,-4.390625 C 4.03125,-4.671875 4.0625,-4.796875 4.125,-4.953125 L 4.0625,-5.03125 c -0.53125,0.046875 -0.859375,0.0625 -1.34375,0.078125 0.046875,-0.140625 0.0625,-0.265625 0.078125,-0.3125 0.25,-1.4375 0.40625,-1.78125 0.828125,-1.78125 0.296875,0 0.46875,0.125 0.796875,0.609375 L 4.59375,-6.46875 C 4.671875,-6.984375 4.75,-7.3125 4.890625,-7.828125 c -0.234375,-0.0625 -0.359375,-0.09375 -0.5,-0.09375 -0.234375,0 -0.359375,0.046875 -0.625,0.21875 -0.3125,0.1875 -0.703125,0.46875 -0.859375,0.609375 L 2.296875,-6.5625 C 1.8125,-6.125 1.6875,-5.90625 1.5625,-5.265625 c -0.03125,0.125 -0.03125,0.15625 -0.046875,0.21875 C 1.40625,-5 1.25,-4.921875 0.96875,-4.84375 L 0.421875,-4.671875 0.375,-4.390625 H 1.359375 L 0.59375,-0.3125 C 0.5625,-0.125 0.515625,0.0625 0.5,0.15625 0.1875,1.828125 0.0625,2.140625 -0.328125,2.140625 -0.5625,2.140625 -0.734375,2 -0.890625,1.65625 L -1.0625,1.6875 C -1.125,2 -1.296875,2.59375 -1.421875,2.859375 -1.3125,2.90625 -1.140625,2.953125 -1,2.953125 -0.625,2.953125 0.046875,2.515625 0.484375,2 1.15625,1.203125 1.484375,0.390625 2,-1.828125 l 0.609375,-2.5625 z m 0,0"
+ id="path587"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph12-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path590"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph12-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.6875,-3.75 1.125,-3.578125 C 0.859375,-3.5 0.71875,-3.46875 0.3125,-3.421875 L 0.234375,-3.40625 V -3.125 l 0.359375,0.03125 c 0.171875,0.015625 0.203125,0.078125 0.203125,0.546875 v 3.78125 c 0,0.4375 -0.046875,0.5 -0.28125,0.515625 L 0.234375,1.765625 V 2.0625 l 1.03125,-0.03125 c 0.09375,0 0.109375,0 1.15625,0.03125 V 1.765625 L 2.0625,1.75 C 1.8125,1.734375 1.765625,1.671875 1.765625,1.234375 V 0 C 2.15625,0.109375 2.28125,0.140625 2.484375,0.140625 2.75,0.140625 3.03125,-0.015625 3.5625,-0.4375 3.625,-0.46875 3.671875,-0.515625 3.703125,-0.546875 4.234375,-0.9375 4.515625,-1.5625 4.515625,-2.28125 4.515625,-3.125 3.90625,-3.75 3.078125,-3.75 2.765625,-3.75 2.53125,-3.671875 2.25,-3.4375 l -0.484375,0.390625 v -0.65625 z m 0.078125,1.109375 C 1.9375,-2.90625 2.203125,-3.03125 2.53125,-3.03125 c 0.609375,0 0.984375,0.46875 0.984375,1.265625 0,0.828125 -0.359375,1.359375 -0.9375,1.359375 -0.34375,0 -0.59375,-0.140625 -0.8125,-0.4375 z m 0,0"
+ id="path593"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph12-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 3.671875,-2.34375 c 0,-0.859375 -0.59375,-1.40625 -1.5,-1.40625 -0.28125,0 -0.484375,0.046875 -0.703125,0.1875 l -0.375,0.21875 c -0.53125,0.3125 -0.765625,0.78125 -0.765625,1.546875 0,1.265625 0.640625,1.9375 1.828125,1.9375 0.453125,0 0.75,-0.078125 1.265625,-0.34375 L 3.59375,-0.59375 3.5,-0.703125 C 3.125,-0.5 2.890625,-0.4375 2.5625,-0.4375 2.15625,-0.4375 1.765625,-0.65625 1.5625,-1 1.4375,-1.21875 1.390625,-1.40625 1.375,-1.78125 h 1.046875 c 0.453125,0 0.8125,-0.046875 1.25,-0.15625 z m -1.6875,0.171875 h -0.03125 c -0.046875,0 -0.25,-0.015625 -0.375,-0.015625 l -0.25,-0.015625 C 1.34375,-2.984375 1.53125,-3.3125 2,-3.3125 c 0.453125,0 0.640625,0.328125 0.65625,1.109375 z m 0,0"
+ id="path596"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph12-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.59375,-1.671875 0.71875,-0.5625 C 0.5625,-0.359375 0.421875,-0.28125 0.171875,-0.265625 V 0 h 0.71875 C 1.125,-0.359375 1.21875,-0.484375 1.3125,-0.625 l 0.5,-0.703125 L 2.609375,0.03125 3.234375,0 C 3.546875,0.015625 3.625,0.015625 3.84375,0.03125 V -0.265625 C 3.609375,-0.296875 3.4375,-0.453125 3.15625,-0.90625 l -0.703125,-1.203125 0.78125,-0.90625 C 3.46875,-3.3125 3.546875,-3.359375 3.84375,-3.359375 V -3.65625 h -0.75 L 2.234375,-2.46875 1.8125,-3.140625 C 1.625,-3.4375 1.484375,-3.625 1.328125,-3.75 c -0.28125,0.0625 -0.875,0.203125 -1.171875,0.25 l 0.0625,0.28125 c 0.046875,0 0.09375,0 0.125,0 0.265625,0 0.40625,0.109375 0.609375,0.46875 z m 0,0"
+ id="path599"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph12-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 2.578125,-0.484375 2.515625,-0.625 c -0.15625,0.078125 -0.234375,0.09375 -0.359375,0.09375 -0.375,0 -0.5,-0.125 -0.5,-0.515625 V -2.9375 H 2.5 L 2.5625,-3.453125 1.65625,-3.40625 V -3.875 c 0,-0.421875 0.03125,-0.6875 0.09375,-1.078125 L 1.640625,-5.03125 c -0.3125,0.140625 -0.5625,0.234375 -0.96875,0.390625 0.015625,0.421875 0.03125,0.5625 0.03125,0.734375 v 0.484375 l -0.53125,0.34375 V -2.90625 L 0.6875,-2.9375 v 2.0625 c 0,0.703125 0.296875,1.015625 0.984375,1.015625 0.25,0 0.453125,-0.0625 0.515625,-0.15625 z m 0,0"
+ id="path602"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph13-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path605"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph13-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.1875,-3.09375 0.25,-2.9375 0.5,-3.09375 c 0.296875,-0.1875 0.328125,-0.203125 0.375,-0.203125 0.09375,0 0.140625,0.078125 0.140625,0.203125 0,0.40625 -0.328125,1.9375 -0.65625,3.078125 l 0.0625,0.09375 C 0.625,0.015625 0.8125,-0.03125 0.984375,-0.0625 c 0.140625,-1 0.3125,-1.515625 0.6875,-2.078125 0.421875,-0.671875 1.015625,-1.15625 1.375,-1.15625 0.09375,0 0.140625,0.0625 0.140625,0.1875 0,0.140625 -0.03125,0.3125 -0.09375,0.5625 l -0.40625,1.6875 C 2.609375,-0.5625 2.578125,-0.375 2.578125,-0.25 c 0,0.203125 0.09375,0.328125 0.25,0.328125 0.203125,0 0.484375,-0.171875 1.265625,-0.75 L 4.015625,-0.828125 3.8125,-0.6875 c -0.234375,0.15625 -0.40625,0.234375 -0.484375,0.234375 -0.0625,0 -0.109375,-0.0625 -0.109375,-0.15625 0,-0.03125 0.015625,-0.125 0.015625,-0.15625 L 3.765625,-2.96875 C 3.8125,-3.203125 3.84375,-3.421875 3.84375,-3.546875 c 0,-0.1875 -0.078125,-0.296875 -0.234375,-0.296875 -0.34375,0 -0.890625,0.3125 -1.359375,0.75 -0.3125,0.265625 -0.53125,0.546875 -0.9375,1.125 L 1.609375,-3.25 C 1.640625,-3.390625 1.65625,-3.484375 1.65625,-3.578125 1.65625,-3.75 1.59375,-3.84375 1.46875,-3.84375 1.3125,-3.84375 1,-3.671875 0.421875,-3.25 Z m 0,0"
+ id="path608"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph14-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path611"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph14-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 4.8125,-1.921875 v -0.46875 H 2.90625 V -4.28125 H 2.4375 v 1.890625 H 0.515625 v 0.46875 H 2.4375 V 0 h 0.46875 v -1.921875 z m 0,0"
+ id="path614"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph15-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path617"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph15-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="m 0.53125,-4.421875 h 0.078125 l 1.03125,-0.46875 c 0.015625,0 0.015625,0 0.03125,0 0.046875,0 0.0625,0.0625 0.0625,0.265625 v 3.859375 c 0,0.421875 -0.09375,0.5 -0.515625,0.53125 L 0.765625,-0.21875 v 0.25 C 1.984375,0 1.984375,0 2.078125,0 2.1875,0 2.359375,0 2.625,0.015625 c 0.09375,0 0.375,0 0.703125,0.015625 v -0.25 L 2.921875,-0.234375 C 2.484375,-0.265625 2.40625,-0.34375 2.40625,-0.765625 v -4.71875 l -0.125,-0.046875 c -0.515625,0.265625 -1.078125,0.515625 -1.796875,0.765625 z m 0,0"
+ id="path620"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph15-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.125,-0.1875 V 0.03125 C 1.625,0 1.625,0 1.90625,0 2.1875,0 2.1875,0 3.734375,0.03125 3.71875,-0.140625 3.71875,-0.21875 3.71875,-0.328125 c 0,-0.109375 0,-0.1875 0.015625,-0.359375 C 2.8125,-0.65625 2.453125,-0.640625 0.96875,-0.609375 L 2.421875,-2.15625 c 0.78125,-0.8125 1.015625,-1.25 1.015625,-1.859375 0,-0.90625 -0.625,-1.46875 -1.640625,-1.46875 -0.5625,0 -0.953125,0.15625 -1.34375,0.546875 L 0.3125,-3.84375 h 0.234375 l 0.09375,-0.375 C 0.765625,-4.671875 1.0625,-4.875 1.59375,-4.875 c 0.6875,0 1.125,0.421875 1.125,1.109375 0,0.59375 -0.34375,1.1875 -1.234375,2.140625 z m 0,0"
+ id="path623"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph15-3"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 1.5,-3.703125 1.421875,-3.734375 C 1.015625,-3.5625 0.609375,-3.453125 0.1875,-3.40625 v 0.21875 h 0.296875 c 0.3125,0 0.34375,0.0625 0.34375,0.578125 V -0.8125 c 0,0.5 -0.015625,0.5625 -0.296875,0.578125 L 0.171875,-0.21875 v 0.25 C 0.96875,0 0.96875,0 1.15625,0 c 0.203125,0 0.203125,0 1,0.03125 v -0.25 L 1.796875,-0.234375 C 1.515625,-0.25 1.5,-0.3125 1.5,-0.8125 Z M 1.125,-5.46875 c -0.234375,0 -0.4375,0.203125 -0.4375,0.4375 0,0.234375 0.203125,0.4375 0.4375,0.4375 0.234375,0 0.4375,-0.203125 0.4375,-0.4375 0,-0.21875 -0.203125,-0.4375 -0.4375,-0.4375 z m 0,0"
+ id="path626"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph15-4"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.265625,0.03125 C 3.75,0 3.765625,0 3.890625,0 c 0.125,0 0.125,0 0.671875,0.03125 v -0.25 L 4.234375,-0.234375 C 3.953125,-0.25 3.9375,-0.296875 3.9375,-0.8125 v -1.53125 c 0,-0.9375 -0.4375,-1.390625 -1.328125,-1.390625 -0.296875,0 -0.46875,0.046875 -0.640625,0.203125 L 1.375,-3.015625 v -0.6875 L 1.296875,-3.734375 C 0.890625,-3.5625 0.484375,-3.453125 0.0625,-3.40625 v 0.21875 h 0.28125 c 0.328125,0 0.359375,0.0625 0.359375,0.578125 V -0.8125 c 0,0.5 -0.03125,0.5625 -0.296875,0.578125 L 0.046875,-0.21875 v 0.25 C 0.59375,0.015625 0.8125,0 1.03125,0 c 0.234375,0 0.453125,0.015625 1,0.03125 v -0.25 L 1.671875,-0.234375 C 1.390625,-0.25 1.375,-0.3125 1.375,-0.8125 V -2.5 c 0,-0.359375 0.515625,-0.75 1,-0.75 0.546875,0 0.890625,0.390625 0.890625,1.015625 z m 0,0"
+ id="path629"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph15-5"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 0.78125,-3.046875 V -0.75 c 0,0.59375 0.265625,0.84375 0.875,0.84375 0.1875,0 0.375,-0.03125 0.421875,-0.09375 L 2.46875,-0.421875 2.359375,-0.5625 c -0.203125,0.109375 -0.3125,0.15625 -0.46875,0.15625 -0.3125,0 -0.4375,-0.15625 -0.4375,-0.546875 v -2.09375 H 2.46875 l 0.078125,-0.421875 -1.09375,0.046875 v -0.3125 c 0,-0.328125 0.015625,-0.609375 0.078125,-1.125 L 1.4375,-4.953125 c -0.1875,0.125 -0.421875,0.234375 -0.671875,0.3125 0.015625,0.234375 0.03125,0.390625 0.03125,0.625 v 0.5625 l -0.625,0.28125 v 0.15625 z m 0,0"
+ id="path632"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph16-0"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d=""
+ id="path635"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph16-1"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.890625,21.140625 C 2.15625,18.53125 1.6875,14.734375 1.6875,10.484375 1.6875,6.25 2.15625,2.4375 3.890625,-0.171875 l -0.15625,-0.46875 c -0.59375,0.90625 -3.15625,3.515625 -3.15625,11.125 0,7.609375 2.5625,10.21875 3.15625,11.125 z m 0,0"
+ id="path638"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ <symbol
+ overflow="visible"
+ id="glyph16-2"
+ style="overflow:visible">
+ <path
+ style="stroke:none"
+ d="M 3.890625,10.484375 C 3.890625,2.875 1.3125,0.265625 0.71875,-0.640625 l -0.140625,0.46875 C 2.3125,2.4375 2.78125,6.25 2.78125,10.484375 c 0,4.25 -0.46875,8.046875 -2.203125,10.65625 l 0.140625,0.46875 c 0.59375,-0.90625 3.171875,-3.515625 3.171875,-11.125 z m 0,0"
+ id="path641"
+ inkscape:connector-curvature="0" />
+ </symbol>
+ </g>
+ </defs>
+ <path
+ inkscape:connector-curvature="0"
+ id="path4370"
+ d="m 28.34765,31.3598 5.78516,0.17969 5.78516,0.25 5.78515,0.34766 5.78125,0.46093 5.78516,0.59766 5.78516,0.76562 5.78515,0.95313 5.78516,1.14453 5.78515,1.32813 5.78516,1.5 5.78516,1.6289 5.78515,1.69141 5.78516,1.66406 5.78125,1.53125 5.78516,1.28125 5.78515,0.89063 5.78516,0.38281 5.78515,-0.23047 5.78516,-0.91406 5.78516,-1.60938 5.78515,-2.30859 5.78516,-2.91406 5.78515,-3.39063 5.78125,-3.69141 5.78516,-3.78125 5.78516,-3.69531 5.78515,-3.39062 5.78516,-2.91407 5.78516,-2.3125 5.78515,-1.625 5.78516,-0.91406 5.78515,-0.23047 5.78516,0.38282 5.78125,0.89453 5.78516,1.27734 5.78515,1.53125 5.78516,1.66406 5.78516,1.69141 5.78515,1.62891 5.78516,1.5039 5.78515,1.33203 5.78516,1.13672 5.78516,0.95313 5.78125,0.76562 5.78515,0.60547 5.78516,0.46094 5.78516,0.34375 5.78515,0.2539 5.78516,0.17579"
+ style="fill:none;stroke:#0000ff;stroke-width:0.79701;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4372"
+ d="M 0,31.00043 H 336.57422"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4374"
+ d="m 340.16406,31.00043 c -1.06641,-0.19922 -2.79297,-0.79688 -3.98828,-1.4961 v 2.98828 c 1.19531,-0.69531 2.92187,-1.29296 3.98828,-1.49218"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <use
+ style="fill:#000000;fill-opacity:1"
+ xlink:href="#glyph9-22"
+ x="454.112"
+ y="693.37201"
+ id="use4376"
+ width="100%"
+ height="100%"
+ transform="translate(-116.67969,-653.27301)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4380"
+ d="M 170.08203,50.84027 V 6.2387097"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4382"
+ d="m 170.08203,2.6527697 c -0.19922,1.0625 -0.79688,2.78906 -1.4961,3.98438 h 2.98829 c -0.69532,-1.19532 -1.29297,-2.92188 -1.49219,-3.98438"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <use
+ style="fill:#000000;fill-opacity:1"
+ xlink:href="#glyph9-16"
+ x="290.59601"
+ y="658.52301"
+ id="use4384"
+ width="100%"
+ height="100%"
+ transform="translate(-116.67969,-653.27301)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4388"
+ d="m 167.24609,13.99261 h 45.35547"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <use
+ style="fill:#000000;fill-opacity:1"
+ xlink:href="#glyph9-23"
+ x="272.21399"
+ y="671.08301"
+ id="use4390"
+ width="100%"
+ height="100%"
+ transform="translate(-116.67969,-653.27301)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4394"
+ d="M 28.34765,107.53558 H 311.8164 V 79.18793 H 28.34765 Z m 0,0"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4396"
+ d="M 31.93359,70.68402 H 308.23047"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4398"
+ d="m 28.34765,70.68402 c 1.0625,0.19922 2.78907,0.79688 3.98438,1.49609 v -2.98828 c -1.19531,0.69532 -2.92188,1.29297 -3.98438,1.49219"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4400"
+ d="m 311.8164,70.68402 c -1.0625,-0.19922 -2.78906,-0.79687 -3.98437,-1.49219 v 2.98828 c 1.19531,-0.69921 2.92187,-1.29687 3.98437,-1.49609"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <use
+ style="fill:#000000;fill-opacity:1"
+ xlink:href="#glyph9-24"
+ x="283.728"
+ y="720.052"
+ id="use4402"
+ width="100%"
+ height="100%"
+ transform="translate(-116.67969,-653.27301)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4406"
+ d="M 311.8164,65.01605 V 76.3559"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4408"
+ d="M 28.34765,65.01605 V 76.3559"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4410"
+ d="M 320.32031,103.94965 V 82.77386"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4412"
+ d="m 320.32031,107.53558 c 0.19922,-1.0625 0.79687,-2.78906 1.49219,-3.98437 h -2.98828 c 0.69921,1.19531 1.29687,2.92187 1.49609,3.98437"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4414"
+ d="m 320.32031,79.18793 c -0.19922,1.0625 -0.79688,2.78906 -1.49609,3.98437 h 2.98828 c -0.69532,-1.19531 -1.29297,-2.92187 -1.49219,-3.98437"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <use
+ style="fill:#000000;fill-opacity:1"
+ xlink:href="#glyph9-3"
+ x="440.832"
+ y="750.59802"
+ id="use4416"
+ width="100%"
+ height="100%"
+ transform="translate(-116.67969,-653.27301)" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4420"
+ d="m 314.64843,79.18793 h 11.33985"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4422"
+ d="m 314.64843,107.53558 h 11.33985"
+ style="fill:none;stroke:#000000;stroke-width:0.3985;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-opacity:1" />
+</svg>
diff --git a/examples/c++/solid_mechanics_model/explicit/images/sphx_glr_explicit.png b/examples/c++/solid_mechanics_model/explicit/images/sphx_glr_explicit.png
new file mode 100644
index 000000000..f3028eb06
Binary files /dev/null and b/examples/c++/solid_mechanics_model/explicit/images/sphx_glr_explicit.png differ
diff --git a/examples/explicit/material.dat b/examples/c++/solid_mechanics_model/explicit/material.dat
similarity index 100%
rename from examples/explicit/material.dat
rename to examples/c++/solid_mechanics_model/explicit/material.dat
diff --git a/examples/implicit/CMakeLists.txt b/examples/c++/solid_mechanics_model/implicit/CMakeLists.txt
similarity index 100%
rename from examples/implicit/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/implicit/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_model/implicit/README.rst b/examples/c++/solid_mechanics_model/implicit/README.rst
new file mode 100644
index 000000000..a624c5378
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/implicit/README.rst
@@ -0,0 +1,73 @@
+implicit (2D)
+'''''''''''''
+
+:Sources:
+
+ .. collapse:: implicit_dynamic.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/implicit/implicit_dynamic.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material_dynamic.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/implicit/material_dynamic.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/`` `implicit <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/implicit>`_
+
+
+In ``implicit``, an example of a dynamic solution with an implicit time integration is shown.
+The implicit scheme is selected using the ``_implicit_dynamic`` constant::
+
+ model.initFull(_analysis_method = _implicit_dynamic);
+
+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-ex-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)
+ \approxeq \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-ex-implicit-dynamic:
+.. figure:: examples/c++/solid_mechanics_model/implicit/images/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-ex-implicit-dynamic_solution` presents the deformed
+beam at 3 different times during the simulation: time steps 0, 1000 and
+2000.
+
+.. _fig-ex-implicit-dynamic_solution:
+.. figure:: examples/c++/solid_mechanics_model/implicit/images/dynamic_analysis.png
+ :align: center
+ :width: 50%
+
+ Deformed beam at three different times (displacement :math:`\times
+ 10`).
diff --git a/examples/implicit/beam.geo b/examples/c++/solid_mechanics_model/implicit/beam.geo
similarity index 100%
rename from examples/implicit/beam.geo
rename to examples/c++/solid_mechanics_model/implicit/beam.geo
diff --git a/examples/c++/solid_mechanics_model/implicit/images/dynamic_analysis.png b/examples/c++/solid_mechanics_model/implicit/images/dynamic_analysis.png
new file mode 100644
index 000000000..0e058f70d
Binary files /dev/null and b/examples/c++/solid_mechanics_model/implicit/images/dynamic_analysis.png differ
diff --git a/examples/c++/solid_mechanics_model/implicit/images/implicit_dynamic.svg b/examples/c++/solid_mechanics_model/implicit/images/implicit_dynamic.svg
new file mode 100644
index 000000000..2404b812e
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/implicit/images/implicit_dynamic.svg
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="635.24872"
+ height="100"
+ id="svg4245"
+ version="1.1"
+ inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
+ sodipodi:docname="implicit_dynamic.svg">
+ <defs
+ id="defs4247">
+ <marker
+ inkscape:stockid="DotS"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="DotS"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path1614"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ transform="scale(0.2) translate(7.4, 1)" />
+ </marker>
+ <marker
+ inkscape:stockid="DotM"
+ orient="auto"
+ refY="0.0"
+ refX="0.0"
+ id="DotM"
+ style="overflow:visible"
+ inkscape:isstock="true">
+ <path
+ id="path1611"
+ d="M -2.5,-1.0 C -2.5,1.7600000 -4.7400000,4.0 -7.5,4.0 C -10.260000,4.0 -12.5,1.7600000 -12.5,-1.0 C -12.5,-3.7600000 -10.260000,-6.0 -7.5,-6.0 C -4.7400000,-6.0 -2.5,-3.7600000 -2.5,-1.0 z "
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
+ transform="scale(0.4) translate(7.4, 1)" />
+ </marker>
+ <linearGradient
+ inkscape:collect="always"
+ id="linearGradient2558">
+ <stop
+ style="stop-color:#afafaf;stop-opacity:1"
+ offset="0"
+ id="stop2554" />
+ <stop
+ id="stop2562"
+ offset="0.48881748"
+ style="stop-color:#cdcdcd;stop-opacity:0.98431373" />
+ <stop
+ style="stop-color:#e9e9e9;stop-opacity:0.97254902"
+ offset="1"
+ id="stop2556" />
+ </linearGradient>
+ <pattern
+ inkscape:collect="always"
+ xlink:href="#Strips1_1"
+ id="pattern2347"
+ patternTransform="matrix(0.90828475,0.92298257,-1.6485622,1.62231,94.330095,111.14521)" />
+ <pattern
+ inkscape:stockid="Stripes 1:1"
+ id="Strips1_1"
+ patternTransform="translate(0,0) scale(10,10)"
+ height="1"
+ width="2"
+ patternUnits="userSpaceOnUse"
+ inkscape:collect="always">
+ <rect
+ id="rect1629"
+ height="2"
+ width="1"
+ y="-0.5"
+ x="0"
+ style="fill:black;stroke:none" />
+ </pattern>
+ <marker
+ inkscape:stockid="TriangleOutL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutL"
+ style="overflow:visible">
+ <path
+ id="path5011"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="scale(0.8)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="TriangleOutM"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="TriangleOutM"
+ style="overflow:visible">
+ <path
+ id="path5014"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="scale(0.4)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path4889"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path4877"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Mend"
+ style="overflow:visible">
+ <path
+ id="path4895"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="scale(-0.6)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path4871"
+ d="M 0,0 5,-5 -12.5,0 5,5 Z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1.00000003pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)"
+ inkscape:connector-curvature="0" />
+ </marker>
+ <pattern
+ inkscape:collect="always"
+ xlink:href="#Strips1_1-7"
+ id="pattern2347-2"
+ patternTransform="matrix(0.90828475,0.92298257,-1.6485622,1.62231,183.20176,207.07339)" />
+ <pattern
+ inkscape:stockid="Stripes 1:1"
+ id="Strips1_1-7"
+ patternTransform="translate(0,0) scale(10,10)"
+ height="1"
+ width="2"
+ patternUnits="userSpaceOnUse"
+ inkscape:collect="always">
+ <rect
+ id="rect1629-0"
+ height="2"
+ width="1"
+ y="-0.5"
+ x="0"
+ style="fill:black;stroke:none" />
+ </pattern>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient2558"
+ id="linearGradient2560"
+ x1="320"
+ y1="151.86218"
+ x2="320"
+ y2="52.862183"
+ gradientUnits="userSpaceOnUse" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.2885298"
+ inkscape:cx="309.57814"
+ inkscape:cy="76.161052"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1920"
+ inkscape:window-height="1152"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:snap-smooth-nodes="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:object-paths="true" />
+ <metadata
+ id="metadata4250">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-2.3756318,-52.362183)">
+ <rect
+ style="fill:url(#linearGradient2560);fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect4253"
+ width="599"
+ height="99"
+ x="20.5"
+ y="52.862183" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:0.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:1.2, 2.4;stroke-dashoffset:0;stroke-opacity:1"
+ d="m 20.5,102.36218 h 599"
+ id="path6455"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <g
+ id="g2511">
+ <rect
+ y="131.93352"
+ x="3.4269824"
+ height="7.9050622"
+ width="34.146034"
+ id="rect911-5"
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.11845864;stroke-miterlimit:4;stroke-dasharray:0.11845865, 0.11845865;stroke-dashoffset:0;stroke-opacity:1" />
+ <rect
+ y="131.93352"
+ x="3.4269879"
+ height="7.9050622"
+ width="34.146034"
+ id="rect911"
+ style="fill:url(#pattern2347);fill-opacity:1;stroke:none;stroke-width:0.11845864;stroke-miterlimit:4;stroke-dasharray:0.11845865, 0.11845865;stroke-dashoffset:0;stroke-opacity:1" />
+ <path
+ inkscape:transform-center-x="3.1575168e-06"
+ inkscape:transform-center-y="-4.9285578"
+ d="m 37.573019,131.93351 -34.1460377,0 L 20.5,102.36218 Z"
+ inkscape:randomized="0"
+ inkscape:rounded="0"
+ inkscape:flatsided="true"
+ sodipodi:arg2="1.5707963"
+ sodipodi:arg1="0.52359878"
+ sodipodi:r2="9.8571119"
+ sodipodi:r1="19.714224"
+ sodipodi:cy="122.0764"
+ sodipodi:cx="20.5"
+ sodipodi:sides="3"
+ id="path2355"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.21399379;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ sodipodi:type="star" />
+ <circle
+ r="2.1285522"
+ cy="102.36218"
+ cx="20.5"
+ id="path2421"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.68048555;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+ </g>
+ <g
+ id="g2533"
+ transform="translate(458.40634,-86.563398)">
+ <g
+ transform="translate(51.721594,-1.3829021)"
+ id="g2518">
+ <rect
+ style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.11845864;stroke-miterlimit:4;stroke-dasharray:0.11845865, 0.11845865;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect911-5-9"
+ width="34.146034"
+ height="7.9050622"
+ x="92.298653"
+ y="227.86171" />
+ <rect
+ style="fill:url(#pattern2347-2);fill-opacity:1;stroke:none;stroke-width:0.11845864;stroke-miterlimit:4;stroke-dasharray:0.11845865, 0.11845865;stroke-dashoffset:0;stroke-opacity:1"
+ id="rect911-3"
+ width="34.146034"
+ height="7.9050622"
+ x="92.29866"
+ y="227.86171" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 91.248047,228.61171 H 127.49609"
+ id="path2466"
+ inkscape:connector-curvature="0" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86301315;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2468"
+ cx="97.500069"
+ cy="224.53729"
+ r="4.0744085" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.86301315;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2468-6"
+ cx="121.24213"
+ cy="224.53729"
+ r="4.0744085" />
+ </g>
+ <g
+ transform="translate(0.40481977,-0.58306837)"
+ id="g2522">
+ <path
+ sodipodi:type="star"
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.21399379;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2355-2"
+ sodipodi:sides="3"
+ sodipodi:cx="160.68884"
+ sodipodi:cy="209.22287"
+ sodipodi:r1="19.714224"
+ sodipodi:r2="9.8571119"
+ sodipodi:arg1="0.52359878"
+ sodipodi:arg2="1.5707963"
+ inkscape:flatsided="true"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="m 177.76186,219.07998 -34.14604,0 17.07302,-29.57133 z"
+ inkscape:transform-center-y="-4.9285578"
+ inkscape:transform-center-x="3.1575168e-06" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.68048555;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+ id="path2421-6"
+ cx="160.68883"
+ cy="189.50867"
+ r="2.1285522" />
+ </g>
+ </g>
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;marker-end:url(#TriangleOutM);marker-start:url(#DotS)"
+ d="M 320,102.36218 V 71.650041"
+ id="path1545"
+ inkscape:connector-curvature="0" />
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot1927"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:1.25;font-family:cmmi10;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;-inkscape-font-specification:cmmi10;font-stretch:normal;font-variant:normal;"
+ transform="translate(2.3756318,52.362183)"><flowRegion
+ id="flowRegion1929"
+ style="-inkscape-font-specification:cmmi10;font-family:cmmi10;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;"><rect
+ id="rect1931"
+ width="35.6996"
+ height="49.499996"
+ x="334.48975"
+ y="0.49999961"
+ style="-inkscape-font-specification:cmmi10;font-family:cmmi10;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;" /></flowRegion><flowPara
+ id="flowPara1933">F</flowPara></flowRoot> </g>
+</svg>
diff --git a/examples/implicit/implicit_dynamic.cc b/examples/c++/solid_mechanics_model/implicit/implicit_dynamic.cc
similarity index 91%
rename from examples/implicit/implicit_dynamic.cc
rename to examples/c++/solid_mechanics_model/implicit/implicit_dynamic.cc
index 31ea8fbfb..a8f13b39e 100644
--- a/examples/implicit/implicit_dynamic.cc
+++ b/examples/c++/solid_mechanics_model/implicit/implicit_dynamic.cc
@@ -1,140 +1,142 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 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)
+ 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<Idx> & trac_nodes =
mesh.getElementGroup("traction").getNodeGroup().getNodes();
bool dump_node = false;
- if (trac_nodes.size() > 0 && mesh.isLocalOrMasterNode(trac_nodes(0))) {
+ if (not trac_nodes.empty() and 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())
+ if (not pos.good()) {
AKANTU_ERROR("Cannot open file \"position.csv\"");
+ }
- pos << "id,time,position,solution" << std::endl;
+ pos << "id,time,position,solution"
+ << "\n";
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 (Int s = 1; time < max_time; ++s, time += time_step) {
- if (prank == 0)
+ if (prank == 0) {
std::cout << s << "\r" << std::flush;
+ }
model.solveStep();
- if (dump_node)
+ if (dump_node) {
pos << s << "," << time << "," << displacment(trac_nodes(0), 1) << ","
- << analytical_solution(s * time_step) << std::endl;
+ << analytical_solution(s * time_step) << "\n";
+ }
- if (s % 100 == 0)
+ if (s % 100 == 0) {
model.dump();
+ }
}
- std::cout << std::endl;
+ std::cout << "\n";
pos.close();
- finalize();
-
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/implicit/material_dynamic.dat b/examples/c++/solid_mechanics_model/implicit/material_dynamic.dat
similarity index 100%
rename from examples/implicit/material_dynamic.dat
rename to examples/c++/solid_mechanics_model/implicit/material_dynamic.dat
diff --git a/examples/io/CMakeLists.txt b/examples/c++/solid_mechanics_model/io/CMakeLists.txt
similarity index 100%
rename from examples/io/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/io/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_model/io/README.rst b/examples/c++/solid_mechanics_model/io/README.rst
new file mode 100644
index 000000000..8529920b1
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/io/README.rst
@@ -0,0 +1,68 @@
+parser (2D)
+'''''''''''
+
+:Sources:
+
+ .. collapse:: example_parser.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/io/parser/example_parser.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: input_file.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/io/parser/input_file.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/io/`` `parser <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/io/parser>`_
+
+In ``io/parser``, an example illustrating how to parse an input file with user-defined parameters is shown. As before, the text input file of the simulation is precised using the method ``initialize``. In the input file, additionally to the usual ``material elastic`` section, there is a section ``user parameters`` with extra user-defined parameters.
+Within the main function, those parameters are retrived with::
+
+ const ParserSection & usersect = getUserParser();
+ Real parameter_name = usersect.getParameter("parameter_name");
+
+dumper (2D)
+'''''''''''
+
+:Sources:
+
+ .. collapse:: dumper_low_level.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/io/dumper/dumper_low_level.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: dumpable_interface.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/io/dumper/dumpable_interface.cc
+ :language: c++
+ :lines: 20-
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/io/`` `dumper <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/io/dumper>`_
+
+In ``io/dumper``, examples of advanced dumping are shown.
+
+``dumper_low_level`` aims at illustrating how to manipulate low-level methods of ``DumperIOHelper``. The goal is to visualize a colorized moving train with Paraview.
+It is shown how to dump only a part of the mesh (here the wheels) using the function ``createElementGroup`` of the mesh object::
+
+ ElementGroup & wheels_elements = mesh.createElementGroup("wheels", spatial_dimension);
+
+One can then add an element to the group with::
+
+ wheels_elements.append(mesh.getElementGroup("lwheel_1"));
+
+where ``lwheel_1`` is the name of the element group in the mesh.
+
+.. _fig-ex-train:
+.. figure:: examples/c++/solid_mechanics_model/io/images/train.gif
+ :align: center
+ :width: 70%
+
+ The wheels and the full train are dumped separately.
+
+``dumpable_interface`` does the same as ``dumper_low_level`` but using ``dumpers::Dumpable`` which is an interface for other classes (Model, Mesh, ...) to dump themselves.
diff --git a/examples/io/dumper/CMakeLists.txt b/examples/c++/solid_mechanics_model/io/dumper/CMakeLists.txt
similarity index 100%
rename from examples/io/dumper/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/io/dumper/CMakeLists.txt
diff --git a/examples/io/dumper/dumpable_interface.cc b/examples/c++/solid_mechanics_model/io/dumper/dumpable_interface.cc
similarity index 97%
rename from examples/io/dumper/dumpable_interface.cc
rename to examples/c++/solid_mechanics_model/io/dumper/dumpable_interface.cc
index c6dc21984..3d90739cf 100644
--- a/examples/io/dumper/dumpable_interface.cc
+++ b/examples/c++/solid_mechanics_model/io/dumper/dumpable_interface.cc
@@ -1,180 +1,177 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "group_manager_inline_impl.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.
+ It is thus 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.
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<Idx> & lnode_1 =
(mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes();
const Array<Idx> & lnode_2 =
(mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes();
const Array<Idx> & rnode_1 =
(mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes();
const Array<Idx> & rnode_2 =
(mesh.getElementGroup("rwheel_2")).getNodeGroup().getNodes();
Array<Real> & node = mesh.getNodes();
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<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<Int> filtered_colour(colour,
wheels_elements.getElements());
auto colour_field_wheel =
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.;
auto nb_steps = 100;
Real theta = tot_displacement / radius;
Vector<Real> l_center(spatial_dimension);
Vector<Real> r_center(spatial_dimension);
for (Int i = 0; i < spatial_dimension; ++i) {
l_center(i) = node(14, i);
r_center(i) = node(2, 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 (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/c++/solid_mechanics_model/io/dumper/dumper_low_level.cc
similarity index 97%
rename from examples/io/dumper/dumper_low_level.cc
rename to examples/c++/solid_mechanics_model/io/dumper/dumper_low_level.cc
index 44f3f8719..408be8ede 100644
--- a/examples/io/dumper/dumper_low_level.cc
+++ b/examples/c++/solid_mechanics_model/io/dumper/dumper_low_level.cc
@@ -1,188 +1,184 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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.
Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("swiss_train.msh");
Array<Real> & nodes = mesh.getNodes();
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<Idx> & lnode_1 =
(mesh.getElementGroup("lwheel_1")).getNodeGroup().getNodes();
const Array<Idx> & lnode_2 =
(mesh.getElementGroup("lwheel_2")).getNodeGroup().getNodes();
const Array<Idx> & rnode_1 =
(mesh.getElementGroup("rwheel_1")).getNodeGroup().getNodes();
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<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<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<Int> filtered_colour(colour,
wheels_elements.getElements());
auto colour_field_wheel =
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.;
Int nb_steps = 100;
Real theta = tot_displacement / radius;
Vector<Real> l_center(3);
Vector<Real> r_center(3);
for (Int i = 0; i < spatial_dimension; ++i) {
l_center(i) = nodes(14, i);
r_center(i) = nodes(2, 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 (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/c++/solid_mechanics_model/io/dumper/locomotive_tools.cc
similarity index 100%
rename from examples/io/dumper/locomotive_tools.cc
rename to examples/c++/solid_mechanics_model/io/dumper/locomotive_tools.cc
diff --git a/examples/io/dumper/locomotive_tools.hh b/examples/c++/solid_mechanics_model/io/dumper/locomotive_tools.hh
similarity index 100%
rename from examples/io/dumper/locomotive_tools.hh
rename to examples/c++/solid_mechanics_model/io/dumper/locomotive_tools.hh
diff --git a/examples/io/dumper/swiss_train.geo b/examples/c++/solid_mechanics_model/io/dumper/swiss_train.geo
similarity index 100%
rename from examples/io/dumper/swiss_train.geo
rename to examples/c++/solid_mechanics_model/io/dumper/swiss_train.geo
diff --git a/examples/c++/solid_mechanics_model/io/images/train.gif b/examples/c++/solid_mechanics_model/io/images/train.gif
new file mode 100644
index 000000000..b7efc64a7
Binary files /dev/null and b/examples/c++/solid_mechanics_model/io/images/train.gif differ
diff --git a/examples/io/parser/CMakeLists.txt b/examples/c++/solid_mechanics_model/io/parser/CMakeLists.txt
similarity index 100%
rename from examples/io/parser/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/io/parser/CMakeLists.txt
diff --git a/examples/io/parser/example_parser.cc b/examples/c++/solid_mechanics_model/io/parser/example_parser.cc
similarity index 93%
rename from examples/io/parser/example_parser.cc
rename to examples/c++/solid_mechanics_model/io/parser/example_parser.cc
index 5c81c6402..da520bdb3 100644
--- a/examples/io/parser/example_parser.cc
+++ b/examples/c++/solid_mechanics_model/io/parser/example_parser.cc
@@ -1,77 +1,72 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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[]) {
// Precise in initialize the name of the text input file to parse.
initialize("input_file.dat", argc, argv);
// Get the user ParserSection.
const ParserSection & usersect = getUserParser();
// getParameterValue() allows to extract data associated to a given parameter
// name
// and cast it in the desired type set as template paramter.
Mesh mesh(usersect.getParameterValue<UInt>("spatial_dimension"));
mesh.read(usersect.getParameterValue<std::string>("mesh_file"));
// getParameter() can be used with variable declaration (destination type is
// explicitly known).
Int max_iter = usersect.getParameter("max_nb_iterations");
Real precision = usersect.getParameter("precision");
// Following NumPy convention, data can be interpreted as Vector or Matrix
// structures.
Matrix<Real> eigen_stress = usersect.getParameter("stress");
SolidMechanicsModel model(mesh);
model.initFull(SolidMechanicsModelOptions(_static));
model.applyBC(BC::Dirichlet::FixedValue(0.0, _x),
usersect.getParameterValue<std::string>("outter_crust"));
model.applyBC(BC::Dirichlet::FixedValue(0.0, _y),
usersect.getParameterValue<std::string>("outter_crust"));
model.applyBC(BC::Neumann::FromStress(eigen_stress),
usersect.getParameterValue<std::string>("inner_holes"));
- model.setDirectory("./paraview");
model.setBaseName("swiss_cheese");
model.addDumpFieldVector("displacement");
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", max_iter);
solver.set("threshold", precision);
model.solveStep();
model.dump();
- finalize();
-
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/io/parser/input_file.dat b/examples/c++/solid_mechanics_model/io/parser/input_file.dat
similarity index 100%
rename from examples/io/parser/input_file.dat
rename to examples/c++/solid_mechanics_model/io/parser/input_file.dat
diff --git a/examples/io/parser/swiss_cheese.geo b/examples/c++/solid_mechanics_model/io/parser/swiss_cheese.geo
similarity index 100%
rename from examples/io/parser/swiss_cheese.geo
rename to examples/c++/solid_mechanics_model/io/parser/swiss_cheese.geo
diff --git a/examples/new_material/CMakeLists.txt b/examples/c++/solid_mechanics_model/new_material/CMakeLists.txt
similarity index 100%
rename from examples/new_material/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/new_material/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_model/new_material/README.rst b/examples/c++/solid_mechanics_model/new_material/README.rst
new file mode 100644
index 000000000..cc67f145f
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/new_material/README.rst
@@ -0,0 +1,29 @@
+new_material (2D)
+'''''''''''''''''
+
+:Sources:
+
+ .. collapse:: new_local_material.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/new_material/new_local_material.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/new_material/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/`` `new_material <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/new_material>`_
+
+
+In ``new_material`` it is shown how to use a user-defined material for the simulation. All the details are described in :ref:`sect-smm-ncl`. The geometry solved is shown in :numref:`fig-ex-new_material`.
+
+.. _fig-ex-new_material:
+.. figure:: examples/c++/solid_mechanics_model/new_material/images/barre_trou.svg
+ :align: center
+ :width: 70%
+
+ Problem geometry.
diff --git a/examples/new_material/barre_trou.geo b/examples/c++/solid_mechanics_model/new_material/barre_trou.geo
similarity index 100%
rename from examples/new_material/barre_trou.geo
rename to examples/c++/solid_mechanics_model/new_material/barre_trou.geo
diff --git a/examples/c++/solid_mechanics_model/new_material/images/barre_trou.svg b/examples/c++/solid_mechanics_model/new_material/images/barre_trou.svg
new file mode 100644
index 000000000..c483b9a7a
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/new_material/images/barre_trou.svg
@@ -0,0 +1,1378 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="162.979mm"
+ height="73mm"
+ viewBox="0 0 162.979 73"
+ version="1.1"
+ id="svg5"
+ xml:space="preserve"
+ inkscape:export-filename="image.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="barre_trou.svg"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview7"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false"
+ inkscape:zoom="1.829812"
+ inkscape:cx="351.12897"
+ inkscape:cy="217.50868"
+ inkscape:window-width="2560"
+ inkscape:window-height="1371"
+ inkscape:window-x="0"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="layer1" /><defs
+ id="defs2"><marker
+ style="overflow:visible"
+ id="Arrow2Lstart"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lstart"
+ inkscape:isstock="true"><path
+ transform="matrix(1.1,0,0,1.1,1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path1673" /></marker><marker
+ style="overflow:visible"
+ id="marker1509"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path1507" /></marker><marker
+ style="overflow:visible"
+ id="marker1373"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path1371" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-0" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-7"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-5" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9-8" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-3-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-6-7" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-0-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-6-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-2-1"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-6-2" /></marker><g
+ id="id-bf7cd927-f269-468f-821e-99504af5ed99-7"><symbol
+ overflow="visible"
+ id="id-a25c6920-9d37-473c-b09a-513886215217-5"><path
+ style="stroke:none"
+ d=""
+ id="id-287ebdd1-0b9c-4f6b-a0f9-ae300f595316-3" /></symbol><symbol
+ overflow="visible"
+ id="id-a457132c-5bfd-4ae1-a5a6-f5172657605f-5"><path
+ style="stroke:none"
+ d="M 3.328125,-3.015625 C 3.390625,-3.265625 3.625,-4.1875 4.3125,-4.1875 c 0.046875,0 0.296875,0 0.5,0.125 C 4.53125,-4 4.34375,-3.765625 4.34375,-3.515625 c 0,0.15625 0.109375,0.34375 0.375,0.34375 0.21875,0 0.53125,-0.171875 0.53125,-0.578125 0,-0.515625 -0.578125,-0.65625 -0.921875,-0.65625 -0.578125,0 -0.921875,0.53125 -1.046875,0.75 -0.25,-0.65625 -0.78125,-0.75 -1.078125,-0.75 -1.03125,0 -1.609375,1.28125 -1.609375,1.53125 0,0.109375 0.109375,0.109375 0.125,0.109375 0.078125,0 0.109375,-0.03125 0.125,-0.109375 0.34375,-1.0625 1,-1.3125 1.34375,-1.3125 0.1875,0 0.53125,0.09375 0.53125,0.671875 0,0.3125 -0.171875,0.96875 -0.53125,2.375 -0.15625,0.609375 -0.515625,1.03125 -0.953125,1.03125 -0.0625,0 -0.28125,0 -0.5,-0.125 0.25,-0.0625 0.46875,-0.265625 0.46875,-0.546875 0,-0.265625 -0.21875,-0.34375 -0.359375,-0.34375 -0.3125,0 -0.546875,0.25 -0.546875,0.578125 0,0.453125 0.484375,0.65625 0.921875,0.65625 0.671875,0 1.03125,-0.703125 1.046875,-0.75 0.125,0.359375 0.484375,0.75 1.078125,0.75 1.03125,0 1.59375,-1.28125 1.59375,-1.53125 0,-0.109375 -0.078125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.046875 -0.140625,0.109375 -0.328125,1.078125 -1,1.3125 -1.3125,1.3125 -0.390625,0 -0.546875,-0.3125 -0.546875,-0.65625 0,-0.21875 0.046875,-0.4375 0.15625,-0.875 z m 0,0"
+ id="id-0f58c18e-89f2-4a50-9310-e19d22ad715c-6" /></symbol></g><g
+ id="id-c3ba0e7a-4468-40d0-bfe7-9671ecde6fe1-9"><symbol
+ overflow="visible"
+ id="id-f135440e-b2eb-4c2c-964b-6a5de2dc70cd-3"><path
+ style="stroke:none"
+ d=""
+ id="id-ad533741-271d-4679-91b1-bd6a2489c323-6" /></symbol><symbol
+ overflow="visible"
+ id="id-d7575b80-e59a-41e2-8032-b108e622f06a-0"><path
+ style="stroke:none"
+ d="m 4.84375,-3.796875 c 0.046875,-0.140625 0.046875,-0.15625 0.046875,-0.234375 0,-0.171875 -0.140625,-0.265625 -0.296875,-0.265625 -0.09375,0 -0.25,0.0625 -0.34375,0.203125 -0.015625,0.0625 -0.109375,0.359375 -0.140625,0.546875 -0.078125,0.25 -0.140625,0.53125 -0.203125,0.796875 l -0.453125,1.796875 c -0.03125,0.140625 -0.46875,0.84375 -1.125,0.84375 -0.5,0 -0.609375,-0.4375 -0.609375,-0.8125 C 1.71875,-1.375 1.890625,-2 2.21875,-2.875 2.375,-3.28125 2.421875,-3.390625 2.421875,-3.59375 c 0,-0.4375 -0.3125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 0.28125,-0.9375 0.671875,-1.234375 1.015625,-1.234375 0.078125,0 0.25,0 0.25,0.3125 0,0.25 -0.109375,0.515625 -0.171875,0.703125 -0.40625,1.0625 -0.578125,1.625 -0.578125,2.09375 0,0.890625 0.625,1.1875 1.21875,1.1875 0.390625,0 0.71875,-0.171875 1,-0.453125 -0.125,0.515625 -0.25,1.015625 -0.640625,1.546875 -0.265625,0.328125 -0.640625,0.625 -1.09375,0.625 -0.140625,0 -0.59375,-0.03125 -0.765625,-0.421875 0.15625,0 0.296875,0 0.421875,-0.125 C 1.328125,1.203125 1.421875,1.0625 1.421875,0.875 1.421875,0.5625 1.15625,0.53125 1.0625,0.53125 0.828125,0.53125 0.5,0.6875 0.5,1.171875 c 0,0.5 0.4375,0.875 1.0625,0.875 1.015625,0 2.046875,-0.90625 2.328125,-2.03125 z m 0,0"
+ id="id-763001b5-8758-4fab-8a27-f252f0bebfb7-6" /></symbol></g><marker
+ style="overflow:visible"
+ id="Arrow2Lstart-7"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lstart"
+ inkscape:isstock="true"><path
+ transform="matrix(1.1,0,0,1.1,1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path1673-9" /></marker><marker
+ style="overflow:visible"
+ id="marker1373-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path1371-0" /></marker><g
+ id="g2113-5"><symbol
+ overflow="visible"
+ id="symbol2107-9"><path
+ style="stroke:none"
+ d=""
+ id="path2105-2" /></symbol><symbol
+ overflow="visible"
+ id="symbol2111-2"><path
+ style="stroke:none"
+ d="m 4.84375,-3.796875 c 0.046875,-0.140625 0.046875,-0.15625 0.046875,-0.234375 0,-0.171875 -0.140625,-0.265625 -0.296875,-0.265625 -0.09375,0 -0.25,0.0625 -0.34375,0.203125 -0.015625,0.0625 -0.109375,0.359375 -0.140625,0.546875 -0.078125,0.25 -0.140625,0.53125 -0.203125,0.796875 l -0.453125,1.796875 c -0.03125,0.140625 -0.46875,0.84375 -1.125,0.84375 -0.5,0 -0.609375,-0.4375 -0.609375,-0.8125 C 1.71875,-1.375 1.890625,-2 2.21875,-2.875 2.375,-3.28125 2.421875,-3.390625 2.421875,-3.59375 c 0,-0.4375 -0.3125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 0.28125,-0.9375 0.671875,-1.234375 1.015625,-1.234375 0.078125,0 0.25,0 0.25,0.3125 0,0.25 -0.109375,0.515625 -0.171875,0.703125 -0.40625,1.0625 -0.578125,1.625 -0.578125,2.09375 0,0.890625 0.625,1.1875 1.21875,1.1875 0.390625,0 0.71875,-0.171875 1,-0.453125 -0.125,0.515625 -0.25,1.015625 -0.640625,1.546875 -0.265625,0.328125 -0.640625,0.625 -1.09375,0.625 -0.140625,0 -0.59375,-0.03125 -0.765625,-0.421875 0.15625,0 0.296875,0 0.421875,-0.125 C 1.328125,1.203125 1.421875,1.0625 1.421875,0.875 1.421875,0.5625 1.15625,0.53125 1.0625,0.53125 0.828125,0.53125 0.5,0.6875 0.5,1.171875 c 0,0.5 0.4375,0.875 1.0625,0.875 1.015625,0 2.046875,-0.90625 2.328125,-2.03125 z m 0,0"
+ id="path2109-8" /></symbol></g><g
+ id="g2505-9"><symbol
+ overflow="visible"
+ id="symbol2499-3"><path
+ style="stroke:none"
+ d=""
+ id="path2497-1" /></symbol><symbol
+ overflow="visible"
+ id="symbol2503-9"><path
+ style="stroke:none"
+ d="m 4.84375,-3.796875 c 0.046875,-0.140625 0.046875,-0.15625 0.046875,-0.234375 0,-0.171875 -0.140625,-0.265625 -0.296875,-0.265625 -0.09375,0 -0.25,0.0625 -0.34375,0.203125 -0.015625,0.0625 -0.109375,0.359375 -0.140625,0.546875 -0.078125,0.25 -0.140625,0.53125 -0.203125,0.796875 l -0.453125,1.796875 c -0.03125,0.140625 -0.46875,0.84375 -1.125,0.84375 -0.5,0 -0.609375,-0.4375 -0.609375,-0.8125 C 1.71875,-1.375 1.890625,-2 2.21875,-2.875 2.375,-3.28125 2.421875,-3.390625 2.421875,-3.59375 c 0,-0.4375 -0.3125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 0.28125,-0.9375 0.671875,-1.234375 1.015625,-1.234375 0.078125,0 0.25,0 0.25,0.3125 0,0.25 -0.109375,0.515625 -0.171875,0.703125 -0.40625,1.0625 -0.578125,1.625 -0.578125,2.09375 0,0.890625 0.625,1.1875 1.21875,1.1875 0.390625,0 0.71875,-0.171875 1,-0.453125 -0.125,0.515625 -0.25,1.015625 -0.640625,1.546875 -0.265625,0.328125 -0.640625,0.625 -1.09375,0.625 -0.140625,0 -0.59375,-0.03125 -0.765625,-0.421875 0.15625,0 0.296875,0 0.421875,-0.125 C 1.328125,1.203125 1.421875,1.0625 1.421875,0.875 1.421875,0.5625 1.15625,0.53125 1.0625,0.53125 0.828125,0.53125 0.5,0.6875 0.5,1.171875 c 0,0.5 0.4375,0.875 1.0625,0.875 1.015625,0 2.046875,-0.90625 2.328125,-2.03125 z m 0,0"
+ id="path2501-4" /></symbol></g><g
+ id="g2596-6"><symbol
+ overflow="visible"
+ id="symbol2590-1"><path
+ style="stroke:none"
+ d=""
+ id="path2588-0" /></symbol><symbol
+ overflow="visible"
+ id="symbol2594-6"><path
+ style="stroke:none"
+ d="m 4.84375,-3.796875 c 0.046875,-0.140625 0.046875,-0.15625 0.046875,-0.234375 0,-0.171875 -0.140625,-0.265625 -0.296875,-0.265625 -0.09375,0 -0.25,0.0625 -0.34375,0.203125 -0.015625,0.0625 -0.109375,0.359375 -0.140625,0.546875 -0.078125,0.25 -0.140625,0.53125 -0.203125,0.796875 l -0.453125,1.796875 c -0.03125,0.140625 -0.46875,0.84375 -1.125,0.84375 -0.5,0 -0.609375,-0.4375 -0.609375,-0.8125 C 1.71875,-1.375 1.890625,-2 2.21875,-2.875 2.375,-3.28125 2.421875,-3.390625 2.421875,-3.59375 c 0,-0.4375 -0.3125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 0.28125,-0.9375 0.671875,-1.234375 1.015625,-1.234375 0.078125,0 0.25,0 0.25,0.3125 0,0.25 -0.109375,0.515625 -0.171875,0.703125 -0.40625,1.0625 -0.578125,1.625 -0.578125,2.09375 0,0.890625 0.625,1.1875 1.21875,1.1875 0.390625,0 0.71875,-0.171875 1,-0.453125 -0.125,0.515625 -0.25,1.015625 -0.640625,1.546875 -0.265625,0.328125 -0.640625,0.625 -1.09375,0.625 -0.140625,0 -0.59375,-0.03125 -0.765625,-0.421875 0.15625,0 0.296875,0 0.421875,-0.125 C 1.328125,1.203125 1.421875,1.0625 1.421875,0.875 1.421875,0.5625 1.15625,0.53125 1.0625,0.53125 0.828125,0.53125 0.5,0.6875 0.5,1.171875 c 0,0.5 0.4375,0.875 1.0625,0.875 1.015625,0 2.046875,-0.90625 2.328125,-2.03125 z m 0,0"
+ id="path2592-3" /></symbol></g><g
+ id="g1139-4"><symbol
+ overflow="visible"
+ id="symbol1133-7"><path
+ style="stroke:none"
+ d=""
+ id="path1131-6" /></symbol><symbol
+ overflow="visible"
+ id="symbol1137-5"><path
+ style="stroke:none"
+ d="M 3.328125,-3.015625 C 3.390625,-3.265625 3.625,-4.1875 4.3125,-4.1875 c 0.046875,0 0.296875,0 0.5,0.125 C 4.53125,-4 4.34375,-3.765625 4.34375,-3.515625 c 0,0.15625 0.109375,0.34375 0.375,0.34375 0.21875,0 0.53125,-0.171875 0.53125,-0.578125 0,-0.515625 -0.578125,-0.65625 -0.921875,-0.65625 -0.578125,0 -0.921875,0.53125 -1.046875,0.75 -0.25,-0.65625 -0.78125,-0.75 -1.078125,-0.75 -1.03125,0 -1.609375,1.28125 -1.609375,1.53125 0,0.109375 0.109375,0.109375 0.125,0.109375 0.078125,0 0.109375,-0.03125 0.125,-0.109375 0.34375,-1.0625 1,-1.3125 1.34375,-1.3125 0.1875,0 0.53125,0.09375 0.53125,0.671875 0,0.3125 -0.171875,0.96875 -0.53125,2.375 -0.15625,0.609375 -0.515625,1.03125 -0.953125,1.03125 -0.0625,0 -0.28125,0 -0.5,-0.125 0.25,-0.0625 0.46875,-0.265625 0.46875,-0.546875 0,-0.265625 -0.21875,-0.34375 -0.359375,-0.34375 -0.3125,0 -0.546875,0.25 -0.546875,0.578125 0,0.453125 0.484375,0.65625 0.921875,0.65625 0.671875,0 1.03125,-0.703125 1.046875,-0.75 0.125,0.359375 0.484375,0.75 1.078125,0.75 1.03125,0 1.59375,-1.28125 1.59375,-1.53125 0,-0.109375 -0.078125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.046875 -0.140625,0.109375 -0.328125,1.078125 -1,1.3125 -1.3125,1.3125 -0.390625,0 -0.546875,-0.3125 -0.546875,-0.65625 0,-0.21875 0.046875,-0.4375 0.15625,-0.875 z m 0,0"
+ id="path1135-6" /></symbol></g><g
+ id="id-c3ba0e7a-4468-40d0-bfe7-9671ecde6fe1-5"><symbol
+ overflow="visible"
+ id="id-f135440e-b2eb-4c2c-964b-6a5de2dc70cd-4"><path
+ style="stroke:none"
+ d=""
+ id="id-ad533741-271d-4679-91b1-bd6a2489c323-7" /></symbol><symbol
+ overflow="visible"
+ id="id-d7575b80-e59a-41e2-8032-b108e622f06a-4"><path
+ style="stroke:none"
+ d="m 4.84375,-3.796875 c 0.046875,-0.140625 0.046875,-0.15625 0.046875,-0.234375 0,-0.171875 -0.140625,-0.265625 -0.296875,-0.265625 -0.09375,0 -0.25,0.0625 -0.34375,0.203125 -0.015625,0.0625 -0.109375,0.359375 -0.140625,0.546875 -0.078125,0.25 -0.140625,0.53125 -0.203125,0.796875 l -0.453125,1.796875 c -0.03125,0.140625 -0.46875,0.84375 -1.125,0.84375 -0.5,0 -0.609375,-0.4375 -0.609375,-0.8125 C 1.71875,-1.375 1.890625,-2 2.21875,-2.875 2.375,-3.28125 2.421875,-3.390625 2.421875,-3.59375 c 0,-0.4375 -0.3125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 0.28125,-0.9375 0.671875,-1.234375 1.015625,-1.234375 0.078125,0 0.25,0 0.25,0.3125 0,0.25 -0.109375,0.515625 -0.171875,0.703125 -0.40625,1.0625 -0.578125,1.625 -0.578125,2.09375 0,0.890625 0.625,1.1875 1.21875,1.1875 0.390625,0 0.71875,-0.171875 1,-0.453125 -0.125,0.515625 -0.25,1.015625 -0.640625,1.546875 -0.265625,0.328125 -0.640625,0.625 -1.09375,0.625 -0.140625,0 -0.59375,-0.03125 -0.765625,-0.421875 0.15625,0 0.296875,0 0.421875,-0.125 C 1.328125,1.203125 1.421875,1.0625 1.421875,0.875 1.421875,0.5625 1.15625,0.53125 1.0625,0.53125 0.828125,0.53125 0.5,0.6875 0.5,1.171875 c 0,0.5 0.4375,0.875 1.0625,0.875 1.015625,0 2.046875,-0.90625 2.328125,-2.03125 z m 0,0"
+ id="id-763001b5-8758-4fab-8a27-f252f0bebfb7-4" /></symbol></g><g
+ id="id-c3ba0e7a-4468-40d0-bfe7-9671ecde6fe1"><symbol
+ overflow="visible"
+ id="id-f135440e-b2eb-4c2c-964b-6a5de2dc70cd"><path
+ style="stroke:none"
+ d=""
+ id="id-ad533741-271d-4679-91b1-bd6a2489c323" /></symbol><symbol
+ overflow="visible"
+ id="id-d7575b80-e59a-41e2-8032-b108e622f06a"><path
+ style="stroke:none"
+ d="m 4.84375,-3.796875 c 0.046875,-0.140625 0.046875,-0.15625 0.046875,-0.234375 0,-0.171875 -0.140625,-0.265625 -0.296875,-0.265625 -0.09375,0 -0.25,0.0625 -0.34375,0.203125 -0.015625,0.0625 -0.109375,0.359375 -0.140625,0.546875 -0.078125,0.25 -0.140625,0.53125 -0.203125,0.796875 l -0.453125,1.796875 c -0.03125,0.140625 -0.46875,0.84375 -1.125,0.84375 -0.5,0 -0.609375,-0.4375 -0.609375,-0.8125 C 1.71875,-1.375 1.890625,-2 2.21875,-2.875 2.375,-3.28125 2.421875,-3.390625 2.421875,-3.59375 c 0,-0.4375 -0.3125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 0.28125,-0.9375 0.671875,-1.234375 1.015625,-1.234375 0.078125,0 0.25,0 0.25,0.3125 0,0.25 -0.109375,0.515625 -0.171875,0.703125 -0.40625,1.0625 -0.578125,1.625 -0.578125,2.09375 0,0.890625 0.625,1.1875 1.21875,1.1875 0.390625,0 0.71875,-0.171875 1,-0.453125 -0.125,0.515625 -0.25,1.015625 -0.640625,1.546875 -0.265625,0.328125 -0.640625,0.625 -1.09375,0.625 -0.140625,0 -0.59375,-0.03125 -0.765625,-0.421875 0.15625,0 0.296875,0 0.421875,-0.125 C 1.328125,1.203125 1.421875,1.0625 1.421875,0.875 1.421875,0.5625 1.15625,0.53125 1.0625,0.53125 0.828125,0.53125 0.5,0.6875 0.5,1.171875 c 0,0.5 0.4375,0.875 1.0625,0.875 1.015625,0 2.046875,-0.90625 2.328125,-2.03125 z m 0,0"
+ id="id-763001b5-8758-4fab-8a27-f252f0bebfb7" /></symbol></g><g
+ id="id-605fab08-d7b5-47c0-b800-d6a4725ba940"><symbol
+ overflow="visible"
+ id="id-9326b4e5-317f-4ada-9f42-fbe7674c7a66"><path
+ style="stroke:none"
+ d=""
+ id="id-043f817f-0ba4-436a-a5b6-4f78679d27cf" /></symbol><symbol
+ overflow="visible"
+ id="id-885b12e7-9cff-4bb4-a049-920b513edb35"><path
+ style="stroke:none"
+ d="m 3.734375,-6.125 c 0.0625,-0.234375 0.09375,-0.328125 0.28125,-0.359375 C 4.109375,-6.5 4.421875,-6.5 4.625,-6.5 c 0.703125,0 1.8125,0 1.8125,0.984375 0,0.34375 -0.15625,1.03125 -0.546875,1.421875 -0.265625,0.25 -0.78125,0.578125 -1.6875,0.578125 H 3.09375 Z m 1.4375,2.734375 c 1.015625,-0.21875 2.1875,-0.921875 2.1875,-1.921875 0,-0.859375 -0.890625,-1.5 -2.203125,-1.5 H 2.328125 c -0.203125,0 -0.296875,0 -0.296875,0.203125 C 2.03125,-6.5 2.125,-6.5 2.3125,-6.5 c 0.015625,0 0.203125,0 0.375,0.015625 0.1875,0.03125 0.265625,0.03125 0.265625,0.171875 0,0.03125 0,0.0625 -0.03125,0.1875 l -1.34375,5.34375 C 1.484375,-0.390625 1.46875,-0.3125 0.671875,-0.3125 0.5,-0.3125 0.40625,-0.3125 0.40625,-0.109375 0.40625,0 0.53125,0 0.546875,0 c 0.28125,0 0.984375,-0.03125 1.25,-0.03125 0.28125,0 1,0.03125 1.28125,0.03125 0.078125,0 0.1875,0 0.1875,-0.203125 0,-0.109375 -0.078125,-0.109375 -0.28125,-0.109375 -0.359375,0 -0.640625,0 -0.640625,-0.171875 0,-0.0625 0.015625,-0.109375 0.03125,-0.171875 l 0.65625,-2.640625 h 1.1875 c 0.90625,0 1.078125,0.5625 1.078125,0.90625 0,0.140625 -0.078125,0.453125 -0.140625,0.6875 C 5.09375,-1.421875 5,-1.0625 5,-0.859375 5,0.21875 6.203125,0.21875 6.328125,0.21875 c 0.84375,0 1.203125,-1 1.203125,-1.140625 0,-0.125 -0.109375,-0.125 -0.125,-0.125 -0.09375,0 -0.109375,0.0625 -0.125,0.140625 C 7.03125,-0.171875 6.59375,0 6.375,0 6.046875,0 5.96875,-0.21875 5.96875,-0.609375 c 0,-0.3125 0.0625,-0.8125 0.109375,-1.140625 0.015625,-0.140625 0.03125,-0.328125 0.03125,-0.46875 0,-0.765625 -0.671875,-1.078125 -0.9375,-1.171875 z m 0,0"
+ id="id-de368909-a8d8-47f1-932f-877850cc5c49" /></symbol></g><g
+ id="id-d6463b7d-bcc4-4958-abcf-265e39c0d110"><symbol
+ overflow="visible"
+ id="id-395f5ea0-cf82-4c17-890c-27d4a96ba80b"><path
+ style="stroke:none"
+ d=""
+ id="id-c925754d-4b75-470e-a88e-942ec81aa6b3" /></symbol><symbol
+ overflow="visible"
+ id="id-eda8493e-0fbf-4a62-95f0-8740ebee06ba"><path
+ style="stroke:none"
+ d="M 7.0625,-2.328125 C 7.078125,-2.375 7.109375,-2.4375 7.109375,-2.46875 c 0,0 0,-0.109375 -0.125,-0.109375 -0.09375,0 -0.109375,0.0625 -0.125,0.125 C 6.203125,-0.984375 5.84375,-0.3125 4.140625,-0.3125 H 2.6875 c -0.140625,0 -0.171875,0 -0.21875,0 -0.109375,-0.015625 -0.140625,-0.03125 -0.140625,-0.109375 0,-0.03125 0,-0.046875 0.046875,-0.21875 L 3.0625,-3.375 h 0.984375 c 0.84375,0 0.84375,0.21875 0.84375,0.46875 0,0.0625 0,0.1875 -0.0625,0.484375 C 4.8125,-2.375 4.796875,-2.34375 4.796875,-2.3125 c 0,0.046875 0.03125,0.109375 0.125,0.109375 C 5,-2.203125 5.03125,-2.25 5.078125,-2.40625 l 0.5625,-2.328125 c 0,-0.0625 -0.046875,-0.109375 -0.125,-0.109375 -0.078125,0 -0.109375,0.0625 -0.125,0.171875 -0.21875,0.765625 -0.390625,1 -1.3125,1 h -0.9375 l 0.59375,-2.40625 C 3.828125,-6.4375 3.84375,-6.46875 4.28125,-6.46875 H 5.6875 c 1.203125,0 1.515625,0.28125 1.515625,1.109375 0,0.234375 0,0.25 -0.046875,0.53125 0,0.046875 -0.015625,0.125 -0.015625,0.171875 0,0.046875 0.03125,0.125 0.125,0.125 0.109375,0 0.125,-0.0625 0.140625,-0.25 L 7.609375,-6.515625 C 7.640625,-6.78125 7.59375,-6.78125 7.34375,-6.78125 H 2.296875 c -0.1875,0 -0.296875,0 -0.296875,0.203125 0,0.109375 0.09375,0.109375 0.28125,0.109375 0.375,0 0.65625,0 0.65625,0.171875 0,0.046875 0,0.0625 -0.0625,0.25 L 1.5625,-0.78125 c -0.09375,0.390625 -0.109375,0.46875 -0.90625,0.46875 -0.171875,0 -0.28125,0 -0.28125,0.1875 C 0.375,0 0.46875,0 0.65625,0 h 5.171875 c 0.234375,0 0.25,-0.015625 0.3125,-0.171875 z m 0,0"
+ id="id-198d3f7a-9d8b-4374-8c22-00017c8782c1" /></symbol><symbol
+ overflow="visible"
+ id="id-5fceb69f-1e58-457e-b7e5-0c88a8acdbd7"><path
+ style="stroke:none"
+ d="m 2.03125,-0.015625 c 0,-0.65625 -0.25,-1.046875 -0.640625,-1.046875 -0.328125,0 -0.53125,0.25 -0.53125,0.53125 C 0.859375,-0.265625 1.0625,0 1.390625,0 1.5,0 1.640625,-0.046875 1.734375,-0.125 1.765625,-0.15625 1.78125,-0.15625 1.78125,-0.15625 c 0.015625,0 0.015625,0 0.015625,0.140625 0,0.75 -0.34375,1.34375 -0.671875,1.671875 -0.109375,0.109375 -0.109375,0.125 -0.109375,0.15625 0,0.078125 0.046875,0.109375 0.09375,0.109375 0.109375,0 0.921875,-0.765625 0.921875,-1.9375 z m 0,0"
+ id="id-cc0a1446-cd18-40ef-86f4-ff7b1b2c932e" /></symbol><symbol
+ overflow="visible"
+ id="id-c0fef717-0577-4576-b7c3-5f45e97c278d"><path
+ style="stroke:none"
+ d="m 2.234375,-4.296875 c 0,-0.015625 0,-0.109375 -0.125,-0.109375 -0.234375,0 -0.96875,0.078125 -1.21875,0.09375 -0.078125,0.015625 -0.1875,0.03125 -0.1875,0.203125 0,0.125 0.078125,0.125 0.234375,0.125 0.484375,0 0.5,0.0625 0.5,0.171875 0,0.0625 -0.125,0.53125 -0.1875,0.796875 L 0.640625,-0.5625 C 0.59375,-0.421875 0.53125,-0.140625 0.53125,-0.125 0.53125,-0.015625 0.625,0 0.6875,0 h 0.140625 c 0.703125,-0.125 1.78125,-0.515625 2.8125,-1.46875 1.3125,-1.21875 1.578125,-2.578125 1.578125,-2.671875 0,-0.171875 -0.109375,-0.265625 -0.28125,-0.265625 -0.078125,0 -0.3125,0.046875 -0.390625,0.328125 -0.640625,2.265625 -2.15625,3.375 -3.296875,3.75 z m 0,0"
+ id="id-5d48412a-d107-47d0-bf04-674be69da0c3" /></symbol></g><g
+ id="id-288209e0-c9b9-4f7b-8c5e-d91d45fdeaaa"><symbol
+ overflow="visible"
+ id="id-790ca78d-7af7-4006-a2ba-c72c934e57dd"><path
+ style="stroke:none"
+ d=""
+ id="id-500536e1-37fe-42fd-a784-ab0bdeb26aa4" /></symbol><symbol
+ overflow="visible"
+ id="id-027d8888-0bd8-4a13-be2c-f14da3f1e0cf"><path
+ style="stroke:none"
+ d="m 3.015625,-3.234375 h 0.96875 c 0.75,0 0.828125,0.15625 0.828125,0.4375 0,0.078125 0,0.1875 -0.0625,0.5 C 4.71875,-2.25 4.71875,-2.21875 4.71875,-2.1875 c 0,0.078125 0.0625,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.203125 L 5.53125,-4.453125 C 5.5625,-4.5625 5.5625,-4.578125 5.5625,-4.609375 5.5625,-4.625 5.546875,-4.71875 5.4375,-4.71875 5.34375,-4.71875 5.328125,-4.671875 5.296875,-4.5 5.078125,-3.734375 4.859375,-3.546875 4,-3.546875 H 3.09375 l 0.640625,-2.53125 C 3.828125,-6.4375 3.84375,-6.46875 4.28125,-6.46875 h 1.3125 c 1.21875,0 1.453125,0.328125 1.453125,1.09375 0,0.234375 0,0.265625 -0.03125,0.546875 C 7,-4.703125 7,-4.6875 7,-4.65625 c 0,0.046875 0.03125,0.125 0.125,0.125 0.109375,0 0.109375,-0.0625 0.125,-0.25 L 7.453125,-6.515625 C 7.484375,-6.78125 7.4375,-6.78125 7.1875,-6.78125 H 2.296875 c -0.1875,0 -0.296875,0 -0.296875,0.203125 0,0.109375 0.09375,0.109375 0.28125,0.109375 0.375,0 0.65625,0 0.65625,0.171875 0,0.046875 0,0.0625 -0.0625,0.25 L 1.5625,-0.78125 c -0.09375,0.390625 -0.109375,0.46875 -0.90625,0.46875 -0.171875,0 -0.28125,0 -0.28125,0.1875 C 0.375,0 0.5,0 0.53125,0 0.8125,0 1.5625,-0.03125 1.84375,-0.03125 2.171875,-0.03125 3,0 3.328125,0 3.421875,0 3.53125,0 3.53125,-0.1875 3.53125,-0.265625 3.484375,-0.296875 3.484375,-0.296875 3.453125,-0.3125 3.421875,-0.3125 3.203125,-0.3125 c -0.21875,0 -0.265625,0 -0.515625,-0.015625 -0.296875,-0.03125 -0.328125,-0.078125 -0.328125,-0.203125 0,-0.015625 0,-0.078125 0.046875,-0.21875 z m 0,0"
+ id="id-12b7509c-b0c1-4b09-96c8-3c0d4ea473e4" /></symbol></g><g
+ id="id-b137a66e-22a7-4792-9de2-46b104400f87"><symbol
+ overflow="visible"
+ id="id-11832709-79c5-4235-aabd-af1c42c67d6c"><path
+ style="stroke:none"
+ d=""
+ id="id-b2f28e49-3c77-4d9b-a95b-699c924ec2ba" /></symbol><symbol
+ overflow="visible"
+ id="id-1edb3990-ec4a-4e7c-b359-83077514a856"><path
+ style="stroke:none"
+ d="M 3.328125,-3.015625 C 3.390625,-3.265625 3.625,-4.1875 4.3125,-4.1875 c 0.046875,0 0.296875,0 0.5,0.125 C 4.53125,-4 4.34375,-3.765625 4.34375,-3.515625 c 0,0.15625 0.109375,0.34375 0.375,0.34375 0.21875,0 0.53125,-0.171875 0.53125,-0.578125 0,-0.515625 -0.578125,-0.65625 -0.921875,-0.65625 -0.578125,0 -0.921875,0.53125 -1.046875,0.75 -0.25,-0.65625 -0.78125,-0.75 -1.078125,-0.75 -1.03125,0 -1.609375,1.28125 -1.609375,1.53125 0,0.109375 0.109375,0.109375 0.125,0.109375 0.078125,0 0.109375,-0.03125 0.125,-0.109375 0.34375,-1.0625 1,-1.3125 1.34375,-1.3125 0.1875,0 0.53125,0.09375 0.53125,0.671875 0,0.3125 -0.171875,0.96875 -0.53125,2.375 -0.15625,0.609375 -0.515625,1.03125 -0.953125,1.03125 -0.0625,0 -0.28125,0 -0.5,-0.125 0.25,-0.0625 0.46875,-0.265625 0.46875,-0.546875 0,-0.265625 -0.21875,-0.34375 -0.359375,-0.34375 -0.3125,0 -0.546875,0.25 -0.546875,0.578125 0,0.453125 0.484375,0.65625 0.921875,0.65625 0.671875,0 1.03125,-0.703125 1.046875,-0.75 0.125,0.359375 0.484375,0.75 1.078125,0.75 1.03125,0 1.59375,-1.28125 1.59375,-1.53125 0,-0.109375 -0.078125,-0.109375 -0.109375,-0.109375 -0.09375,0 -0.109375,0.046875 -0.140625,0.109375 -0.328125,1.078125 -1,1.3125 -1.3125,1.3125 -0.390625,0 -0.546875,-0.3125 -0.546875,-0.65625 0,-0.21875 0.046875,-0.4375 0.15625,-0.875 z m 0,0"
+ id="id-f8e49c21-65b6-48cd-9a95-1fd5e8812316" /></symbol></g><g
+ id="id-ae4e527d-c8f9-441a-ab0c-6b205ce3c960"><symbol
+ overflow="visible"
+ id="id-9f88cd57-85f8-48ca-93d2-7950b91d3e4c"><path
+ style="stroke:none"
+ d=""
+ id="id-af12f0e9-33c1-48a4-9078-027653d27edd" /></symbol><symbol
+ overflow="visible"
+ id="id-39521aa7-3cdc-43be-bb6e-5300b2b36a70"><path
+ style="stroke:none"
+ d="m 1.265625,-0.765625 1.0625,-1.03125 c 1.546875,-1.375 2.140625,-1.90625 2.140625,-2.90625 0,-1.140625 -0.890625,-1.9375 -2.109375,-1.9375 -1.125,0 -1.859375,0.921875 -1.859375,1.8125 0,0.546875 0.5,0.546875 0.53125,0.546875 0.171875,0 0.515625,-0.109375 0.515625,-0.53125 0,-0.25 -0.1875,-0.515625 -0.53125,-0.515625 -0.078125,0 -0.09375,0 -0.125,0.015625 0.21875,-0.65625 0.765625,-1.015625 1.34375,-1.015625 0.90625,0 1.328125,0.8125 1.328125,1.625 C 3.5625,-3.90625 3.078125,-3.125 2.515625,-2.5 l -1.90625,2.125 C 0.5,-0.265625 0.5,-0.234375 0.5,0 H 4.203125 L 4.46875,-1.734375 H 4.234375 C 4.171875,-1.4375 4.109375,-1 4,-0.84375 3.9375,-0.765625 3.28125,-0.765625 3.0625,-0.765625 Z m 0,0"
+ id="id-c53da5bf-f8bf-46dc-94f6-331cd499f637" /></symbol><symbol
+ overflow="visible"
+ id="id-6cd10e36-9c00-42f3-9e56-0268e1a01d00"><path
+ style="stroke:none"
+ d=""
+ id="id-250e72c3-81ac-445e-b523-6067e3c02955" /></symbol><symbol
+ overflow="visible"
+ id="id-57e85956-a6fb-48c4-91c0-6cd8b8263de7"><path
+ style="stroke:none"
+ d="m 2.578125,-6.8125 c 0,0 0,-0.109375 -0.140625,-0.109375 -0.21875,0 -0.953125,0.078125 -1.21875,0.109375 -0.078125,0 -0.1875,0.015625 -0.1875,0.203125 0,0.109375 0.109375,0.109375 0.25,0.109375 0.484375,0 0.5,0.09375 0.5,0.171875 L 1.75,-6.125 0.484375,-1.140625 C 0.453125,-1.03125 0.4375,-0.96875 0.4375,-0.8125 c 0,0.578125 0.4375,0.921875 0.90625,0.921875 0.328125,0 0.578125,-0.203125 0.75,-0.5625 0.171875,-0.375 0.296875,-0.953125 0.296875,-0.96875 0,-0.109375 -0.09375,-0.109375 -0.125,-0.109375 -0.09375,0 -0.109375,0.046875 -0.125,0.1875 C 1.96875,-0.703125 1.78125,-0.109375 1.375,-0.109375 c -0.296875,0 -0.296875,-0.3125 -0.296875,-0.453125 0,-0.25 0.015625,-0.296875 0.0625,-0.484375 z m 0,0"
+ id="id-d31f98e7-12c3-4a2b-8145-45eb087f8d34" /></symbol></g><g
+ id="id-c3e16978-6f6b-4620-9c5f-ddca488834e9"><symbol
+ overflow="visible"
+ id="id-b0ae37c2-096d-4b15-ae0e-46b32bee8d9a"><path
+ style="stroke:none"
+ d=""
+ id="id-385a1233-5d92-483c-8ac5-b6d97c04a975" /></symbol><symbol
+ overflow="visible"
+ id="id-f7a2a0d8-b7cc-4bbf-b530-96d3d5c621d3"><path
+ style="stroke:none"
+ d="m 1.265625,-0.765625 1.0625,-1.03125 c 1.546875,-1.375 2.140625,-1.90625 2.140625,-2.90625 0,-1.140625 -0.890625,-1.9375 -2.109375,-1.9375 -1.125,0 -1.859375,0.921875 -1.859375,1.8125 0,0.546875 0.5,0.546875 0.53125,0.546875 0.171875,0 0.515625,-0.109375 0.515625,-0.53125 0,-0.25 -0.1875,-0.515625 -0.53125,-0.515625 -0.078125,0 -0.09375,0 -0.125,0.015625 0.21875,-0.65625 0.765625,-1.015625 1.34375,-1.015625 0.90625,0 1.328125,0.8125 1.328125,1.625 C 3.5625,-3.90625 3.078125,-3.125 2.515625,-2.5 l -1.90625,2.125 C 0.5,-0.265625 0.5,-0.234375 0.5,0 H 4.203125 L 4.46875,-1.734375 H 4.234375 C 4.171875,-1.4375 4.109375,-1 4,-0.84375 3.9375,-0.765625 3.28125,-0.765625 3.0625,-0.765625 Z m 0,0"
+ id="id-8eb8ced3-9a4f-4d22-ab3d-e9ba306d4518" /></symbol><symbol
+ overflow="visible"
+ id="id-9832ff88-d07d-4962-9519-17cfd5655225"><path
+ style="stroke:none"
+ d=""
+ id="id-1d9aa595-6499-4a84-9d95-f9b5c4169308" /></symbol><symbol
+ overflow="visible"
+ id="id-1060d56a-c8e6-43fa-a88c-858b37d6472c"><path
+ style="stroke:none"
+ d="M 4.609375,-3.375 C 4.65625,-3.59375 4.75,-3.96875 4.75,-4.03125 c 0,-0.171875 -0.140625,-0.265625 -0.28125,-0.265625 -0.125,0 -0.296875,0.078125 -0.375,0.28125 -0.03125,0.0625 -0.5,1.96875 -0.5625,2.234375 C 3.453125,-1.484375 3.4375,-1.3125 3.4375,-1.125 c 0,0.109375 0,0.125 0.015625,0.171875 -0.234375,0.53125 -0.53125,0.84375 -0.921875,0.84375 -0.796875,0 -0.796875,-0.734375 -0.796875,-0.90625 0,-0.3125 0.046875,-0.703125 0.515625,-1.9375 0.109375,-0.296875 0.171875,-0.4375 0.171875,-0.640625 0,-0.4375 -0.328125,-0.8125 -0.8125,-0.8125 -0.953125,0 -1.3125,1.453125 -1.3125,1.53125 0,0.109375 0.09375,0.109375 0.109375,0.109375 0.109375,0 0.109375,-0.03125 0.15625,-0.1875 C 0.84375,-3.875 1.21875,-4.1875 1.578125,-4.1875 c 0.09375,0 0.25,0.015625 0.25,0.328125 0,0.25 -0.109375,0.53125 -0.1875,0.703125 -0.4375,1.171875 -0.546875,1.625 -0.546875,2.015625 0,0.90625 0.65625,1.25 1.40625,1.25 0.171875,0 0.640625,0 1.03125,-0.703125 0.265625,0.640625 0.953125,0.703125 1.25,0.703125 0.75,0 1.1875,-0.625 1.453125,-1.21875 0.328125,-0.78125 0.65625,-2.125 0.65625,-2.59375 0,-0.546875 -0.265625,-0.703125 -0.4375,-0.703125 -0.25,0 -0.5,0.265625 -0.5,0.484375 0,0.125 0.0625,0.1875 0.140625,0.265625 0.109375,0.109375 0.359375,0.359375 0.359375,0.84375 0,0.34375 -0.28125,1.3125 -0.546875,1.828125 -0.25,0.53125 -0.609375,0.875 -1.09375,0.875 -0.46875,0 -0.734375,-0.296875 -0.734375,-0.875 0,-0.265625 0.0625,-0.578125 0.109375,-0.71875 z m 0,0"
+ id="id-8cad3ed5-eef8-4661-833d-a2063db6336a" /></symbol></g><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-13.306989,-8.8788833)"><circle
+ fill="#5a5a5a"
+ cx="21.017509"
+ cy="74.330238"
+ r="0.23654085"
+ id="circle188"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="166.32173"
+ cy="74.330238"
+ r="0.23654085"
+ id="circle190"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="166.32173"
+ cy="16.208838"
+ r="0.23654085"
+ id="circle192"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="21.017509"
+ cy="16.208838"
+ r="0.23654085"
+ id="circle194"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="93.66938"
+ cy="45.269539"
+ r="0.23654085"
+ id="circle196"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="71.873795"
+ cy="45.269539"
+ r="0.23654085"
+ id="circle198"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="115.46544"
+ cy="45.269539"
+ r="0.23654085"
+ id="circle200"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="93.66938"
+ cy="67.065125"
+ r="0.23654085"
+ id="circle202"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="93.66938"
+ cy="23.473951"
+ r="0.23654085"
+ id="circle204"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><circle
+ fill="#5a5a5a"
+ cx="93.66938"
+ cy="23.473951"
+ r="0.23654085"
+ id="circle206"
+ style="fill:none;stroke:#000000;stroke-width:0.11827;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="245.714,726.214 1474.29,726.214 1474.29,234.786 245.714,234.786 245.714,726.214"
+ id="polyline208"
+ transform="matrix(0.11827043,0,0,0.11827043,-8.0431907,-11.559404)"
+ style="fill:none;stroke:#000000;stroke-width:3.69492;stroke-dasharray:none;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="675.714,480.5 675.75,476.882 675.856,473.265 676.034,469.651 676.282,466.041 676.602,462.437 676.992,458.84 677.452,455.251 677.983,451.671 678.584,448.103 679.255,444.548 679.996,441.006 680.806,437.479 681.685,433.969 682.633,430.477 683.65,427.005 684.734,423.553 685.886,420.122 687.105,416.716 688.39,413.333 689.742,409.977 691.16,406.648 692.642,403.347 694.189,400.076 695.8,396.836 697.474,393.628 699.211,390.454 701.01,387.315 702.871,384.211 704.791,381.145 706.772,378.116 708.812,375.128 710.91,372.18 713.065,369.273 715.277,366.41 717.545,363.59 719.868,360.816 722.245,358.088 724.675,355.407 727.157,352.774 729.69,350.19 732.274,347.657 734.907,345.175 737.588,342.745 740.316,340.368 743.09,338.045 745.91,335.777 748.773,333.565 751.68,331.41 754.628,329.312 757.616,327.272 760.644,325.291 763.711,323.371 766.815,321.51 769.954,319.711 773.128,317.974 776.336,316.3 779.576,314.689 782.847,313.142 786.148,311.66 789.477,310.242 792.833,308.89 796.216,307.605 799.622,306.386 803.053,305.234 806.505,304.15 809.977,303.133 813.469,302.185 816.979,301.306 820.506,300.496 824.048,299.755 827.603,299.084 831.171,298.483 834.751,297.952 838.34,297.492 841.937,297.102 845.541,296.782 849.151,296.534 852.765,296.356 856.382,296.25 860,296.214 863.618,296.25 867.235,296.356 870.849,296.534 874.459,296.782 878.063,297.102 881.66,297.492 885.249,297.952 888.829,298.483 892.397,299.084 895.952,299.755 899.494,300.496 903.021,301.306 906.531,302.185 910.023,303.133 913.495,304.15 916.947,305.234 920.378,306.386 923.784,307.605 927.167,308.89 930.523,310.242 933.852,311.66 937.153,313.142 940.424,314.689 943.664,316.3 946.872,317.974 950.046,319.711 953.185,321.51 956.289,323.371 959.356,325.291 962.384,327.272 965.372,329.312 968.32,331.41 971.227,333.565 974.09,335.777 976.91,338.045 979.684,340.368 982.412,342.745 985.093,345.175 987.726,347.657 990.31,350.19 992.843,352.774 995.325,355.407 997.755,358.088 1000.13,360.816 1002.45,363.59 1004.72,366.41 1006.93,369.273 1009.09,372.18 1011.19,375.128 1013.23,378.116 1015.21,381.145 1017.13,384.211 1018.99,387.315 1020.79,390.454 1022.53,393.628 1024.2,396.836 1025.81,400.076 1027.36,403.347 1028.84,406.648 1030.26,409.977 1031.61,413.333 1032.9,416.716 1034.11,420.122 1035.27,423.553 1036.35,427.005 1037.37,430.477 1038.31,433.969 1039.19,437.479 1040,441.006 1040.74,444.548 1041.42,448.103 1042.02,451.671 1042.55,455.251 1043.01,458.84 1043.4,462.437 1043.72,466.041 1043.97,469.651 1044.14,473.265 1044.25,476.882 1044.29,480.5 1044.25,484.118 1044.14,487.735 1043.97,491.349 1043.72,494.959 1043.4,498.563 1043.01,502.16 1042.55,505.749 1042.02,509.329 1041.42,512.897 1040.74,516.452 1040,519.994 1039.19,523.521 1038.31,527.031 1037.37,530.523 1036.35,533.995 1035.27,537.447 1034.11,540.878 1032.9,544.284 1031.61,547.667 1030.26,551.023 1028.84,554.352 1027.36,557.653 1025.81,560.924 1024.2,564.164 1022.53,567.372 1020.79,570.546 1018.99,573.685 1017.13,576.789 1015.21,579.855 1013.23,582.884 1011.19,585.872 1009.09,588.82 1006.93,591.727 1004.72,594.59 1002.45,597.41 1000.13,600.184 997.755,602.912 995.325,605.593 992.843,608.226 990.31,610.81 987.726,613.343 985.093,615.825 982.412,618.255 979.684,620.632 976.91,622.955 974.09,625.223 971.227,627.435 968.32,629.59 965.372,631.688 962.384,633.728 959.356,635.709 956.289,637.629 953.185,639.49 950.046,641.289 946.872,643.026 943.664,644.7 940.424,646.311 937.153,647.858 933.852,649.34 930.523,650.758 927.167,652.11 923.784,653.395 920.378,654.614 916.947,655.766 913.495,656.85 910.023,657.867 906.531,658.815 903.021,659.694 899.494,660.504 895.952,661.245 892.397,661.916 888.829,662.517 885.249,663.048 881.66,663.508 878.063,663.898 874.459,664.218 870.849,664.466 867.235,664.644 863.618,664.75 860,664.786 856.382,664.75 852.765,664.644 849.151,664.466 845.541,664.218 841.937,663.898 838.34,663.508 834.751,663.048 831.171,662.517 827.603,661.916 824.048,661.245 820.506,660.504 816.979,659.694 813.469,658.815 809.977,657.867 806.505,656.85 803.053,655.766 799.622,654.614 796.216,653.395 792.833,652.11 789.477,650.758 786.148,649.34 782.847,647.858 779.576,646.311 776.336,644.7 773.128,643.026 769.954,641.289 766.815,639.49 763.711,637.629 760.644,635.709 757.616,633.728 754.628,631.688 751.68,629.59 748.773,627.435 745.91,625.223 743.09,622.955 740.316,620.632 737.588,618.255 734.907,615.825 732.274,613.343 729.69,610.81 727.157,608.226 724.675,605.593 722.245,602.912 719.868,600.184 717.545,597.41 715.277,594.59 713.065,591.727 710.91,588.82 708.812,585.872 706.772,582.884 704.791,579.855 702.871,576.789 701.01,573.685 699.211,570.546 697.474,567.372 695.8,564.164 694.189,560.924 692.642,557.653 691.16,554.352 689.742,551.023 688.39,547.667 687.105,544.284 685.886,540.878 684.734,537.447 683.65,533.995 682.633,530.523 681.685,527.031 680.806,523.521 679.996,519.994 679.255,516.452 678.584,512.897 677.983,509.329 677.452,505.749 676.992,502.16 676.602,498.563 676.282,494.959 676.034,491.349 675.856,487.735 675.75,484.118 675.714,480.5"
+ id="polyline210"
+ transform="matrix(0.11827043,0,0,0.11827043,-8.0431907,-11.559404)"
+ style="fill:none;stroke:#000000;stroke-width:3.69492;stroke-dasharray:none;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1660,921"
+ id="polyline216"
+ transform="matrix(0.11827043,0,0,0.11827043,-8.0431907,-11.559404)" /><text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+ x="103.2864"
+ y="95.054565"
+ id="text2333"><tspan
+ sodipodi:role="line"
+ id="tspan2331"
+ x="103.2864"
+ y="95.054565"
+ style="stroke-width:0.264583" /></text><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3)"
+ d="m 167.82359,17.700215 h 7.65815"
+ id="path857-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5)"
+ d="m 167.82359,22.101058 h 7.65815"
+ id="path857-7-5"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6)"
+ d="m 167.82359,26.863516 h 7.65815"
+ id="path857-7-2"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9)"
+ d="m 167.82359,31.264352 h 7.65815"
+ id="path857-7-5-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0)"
+ d="m 167.64049,35.81928 h 7.65815"
+ id="path857-7-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-3)"
+ d="m 167.64049,40.220116 h 7.65815"
+ id="path857-7-5-8"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-0)"
+ d="m 167.64049,44.982574 h 7.65815"
+ id="path857-7-2-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-2)"
+ d="m 167.64049,49.38341 h 7.65815"
+ id="path857-7-5-7-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-2)"
+ d="m 167.57437,54.449677 h 7.65815"
+ id="path857-7-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-2)"
+ d="m 167.57437,58.850514 h 7.65815"
+ id="path857-7-5-3"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-7)"
+ d="m 167.57437,63.612959 h 7.65815"
+ id="path857-7-2-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-9)"
+ d="m 167.57437,68.013812 h 7.65815"
+ id="path857-7-5-7-94"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.298896px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0-2)"
+ d="m 167.39127,72.568735 h 7.65815"
+ id="path857-7-1-7"
+ sodipodi:nodetypes="cc" /><g
+ id="g4256"
+ transform="matrix(0.17201065,0,0,0.1969014,-5.3789008,-32.220675)"><g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" /></g></g><g
+ id="g4256-36"
+ transform="matrix(0.17201065,0,0,0.1969014,-5.1917441,25.524781)"><g
+ id="g2882-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62" /></g></g><g
+ id="g9336"
+ transform="matrix(1.0532618,0,0,0.9991344,-1.2256784,-5.1470167)"><g
+ id="g4256-36-8"
+ transform="matrix(0,-0.17201065,0.1969014,0,-27.647856,105.40788)"><g
+ id="g2882-7-9"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4" /></g></g><g
+ id="g4256-36-8-4"
+ transform="matrix(0,-0.17201065,0.1969014,0,6.894128,105.40788)"><g
+ id="g2882-7-9-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7" /></g></g><g
+ id="g4256-36-8-5"
+ transform="matrix(0,-0.17201065,0.1969014,0,41.436112,105.40788)"><g
+ id="g2882-7-9-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5" /></g></g><g
+ id="g4256-36-8-5-6"
+ transform="matrix(0,-0.17201065,0.1969014,0,75.978096,105.40788)"><g
+ id="g2882-7-9-0-2"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6" /></g></g><g
+ id="g4256-36-8-5-6-1"
+ transform="matrix(0,-0.17201065,0.1969014,0,110.52008,105.40788)"><g
+ id="g2882-7-9-0-2-8"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8" /></g></g></g><g
+ id="g9336-9"
+ transform="matrix(-1.0532618,0,0,-0.9991344,188.69023,95.525807)"><g
+ id="g4256-36-8-7"
+ transform="matrix(0,-0.17201065,0.1969014,0,-27.647856,105.40788)"><g
+ id="g2882-7-9-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-61"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-47" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-50" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-6" /></g></g><g
+ id="g4256-36-8-4-1"
+ transform="matrix(0,-0.17201065,0.1969014,0,6.894128,105.40788)"><g
+ id="g2882-7-9-7-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7-1"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7-5" /></g></g><g
+ id="g4256-36-8-5-69"
+ transform="matrix(0,-0.17201065,0.1969014,0,41.436112,105.40788)"><g
+ id="g2882-7-9-0-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-7" /></g></g><g
+ id="g4256-36-8-5-6-8"
+ transform="matrix(0,-0.17201065,0.1969014,0,75.978096,105.40788)"><g
+ id="g2882-7-9-0-2-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-4"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-9" /></g></g><g
+ id="g4256-36-8-5-6-1-2"
+ transform="matrix(0,-0.17201065,0.1969014,0,110.52008,105.40788)"><g
+ id="g2882-7-9-0-2-8-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0-5"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8-7" /></g></g></g><g
+ id="g4256-36-6"
+ transform="matrix(0.17201065,0,0,0.1969014,-5.3109612,-3.4159598)"><g
+ id="g2882-7-1"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-7"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-2"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-2" /></g></g></g></svg>
diff --git a/examples/new_material/local_material_damage.cc b/examples/c++/solid_mechanics_model/new_material/local_material_damage.cc
similarity index 92%
rename from examples/new_material/local_material_damage.cc
rename to examples/c++/solid_mechanics_model/new_material/local_material_damage.cc
index 4b133faa2..a434319d8 100644
--- a/examples/new_material/local_material_damage.cc
+++ b/examples/c++/solid_mechanics_model/new_material/local_material_damage.cc
@@ -1,98 +1,96 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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) {
+ : Material(model, id), damage(this->registerInternal("damage", 1)) {
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).data();
+ auto dam = damage(el_type, ghost_type).begin();
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).data();
+ auto epot = potential_energy(el_type).begin();
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN(el_type, _not_ghost);
computePotentialEnergyOnQuad(grad_u, sigma, *epot);
- epot++;
+ ++epot;
MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
AKANTU_DEBUG_OUT();
}
-static bool material_is_alocated_local_damage [[gnu::unused]] =
+const bool material_is_alocated_local_damage [[maybe_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/c++/solid_mechanics_model/new_material/local_material_damage.hh
similarity index 85%
rename from examples/new_material/local_material_damage.hh
rename to examples/c++/solid_mechanics_model/new_material/local_material_damage.hh
index a7943f1ff..30ad79efb 100644
--- a/examples/new_material/local_material_damage.hh
+++ b/examples/c++/solid_mechanics_model/new_material/local_material_damage.hh
@@ -1,109 +1,107 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(SolidMechanicsModel & model, const ID & id = "");
/* ------------------------------------------------------------------------ */
/* 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
template <typename D1, typename D2>
- inline void computeStressOnQuad(Eigen::MatrixBase<D1> &grad_u,
- Eigen::MatrixBase<D2> &sigma, Real &damage);
+ inline void computeStressOnQuad(Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & sigma, Real & damage);
/// compute the potential energy for on element
template <typename D1, typename D2>
- inline void computePotentialEnergyOnQuad(Eigen::MatrixBase<D1> &grad_u,
- Eigen::MatrixBase<D2> &sigma,
- Real &epot);
+ 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;
+ [[nodiscard]] 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;
+ Real E{};
/// Poisson coefficient
- Real nu;
+ Real nu{};
/// First Lamé coefficient
- Real lambda;
+ Real lambda{};
/// Second Lamé coefficient (shear modulus)
- Real mu;
+ Real mu{};
/// resistance to damage
- Real Yd;
+ Real Yd{};
/// damage threshold
- Real Sd;
+ Real Sd{};
/// Bulk modulus
- Real kpa;
+ Real kpa{};
/// damage internal variable
- InternalField<Real> damage;
+ InternalField<Real> & damage;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
-#include "local_material_damage_inline_impl.hh"
+#include "local_material_damage_inline_impl.hh" // NOLINT(unused-includes)
#endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_HH_ */
diff --git a/examples/new_material/local_material_damage_inline_impl.hh b/examples/c++/solid_mechanics_model/new_material/local_material_damage_inline_impl.hh
similarity index 100%
rename from examples/new_material/local_material_damage_inline_impl.hh
rename to examples/c++/solid_mechanics_model/new_material/local_material_damage_inline_impl.hh
diff --git a/examples/new_material/material.dat b/examples/c++/solid_mechanics_model/new_material/material.dat
similarity index 100%
rename from examples/new_material/material.dat
rename to examples/c++/solid_mechanics_model/new_material/material.dat
diff --git a/examples/new_material/new_local_material.cc b/examples/c++/solid_mechanics_model/new_material/new_local_material.cc
similarity index 87%
rename from examples/new_material/new_local_material.cc
rename to examples/c++/solid_mechanics_model/new_material/new_local_material.cc
index a10970ccf..72f06c1f7 100644
--- a/examples/new_material/new_local_material.cc
+++ b/examples/c++/solid_mechanics_model/new_material/new_local_material.cc
@@ -1,91 +1,89 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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);
Int max_steps = 10000;
- Real epot, ekin;
+ Real epot{0.};
+ Real ekin{0.};
- const Int spatial_dimension = 2;
+ const Int dim = 2;
- Mesh mesh(spatial_dimension);
+ Mesh mesh(dim);
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;
+ std::cout << model.getMaterial(0) << "\n";
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);
+ Matrix<Real> stress(dim, dim);
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 (Int s = 0; s < max_steps; ++s) {
model.solveStep();
epot = model.getEnergy("potential");
ekin = model.getEnergy("kinetic");
- if (s % 100 == 0)
+ if (s % 100 == 0) {
std::cout << s << " " << epot << " " << ekin << " " << epot + ekin
- << std::endl;
+ << "\n";
+ }
- if (s % 1000 == 0)
+ if (s % 1000 == 0) {
model.dump();
+ }
}
- akantu::finalize();
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/new_material/viscoelastic_maxwell/CMakeLists.txt b/examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/CMakeLists.txt
similarity index 100%
rename from examples/new_material/viscoelastic_maxwell/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/CMakeLists.txt
diff --git a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell.dat b/examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell.dat
similarity index 100%
rename from examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell.dat
rename to examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell.dat
diff --git a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc b/examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc
similarity index 100%
rename from examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc
rename to examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_energies.cc
diff --git a/examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_mesh.geo b/examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_mesh.geo
similarity index 100%
rename from examples/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_mesh.geo
rename to examples/c++/solid_mechanics_model/new_material/viscoelastic_maxwell/material_viscoelastic_maxwell_mesh.geo
diff --git a/examples/parallel/CMakeLists.txt b/examples/c++/solid_mechanics_model/parallel/CMakeLists.txt
similarity index 100%
rename from examples/parallel/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/parallel/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_model/parallel/README.rst b/examples/c++/solid_mechanics_model/parallel/README.rst
new file mode 100644
index 000000000..9ef74c573
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/parallel/README.rst
@@ -0,0 +1,45 @@
+parallel (2D)
+'''''''''''''
+
+:Sources:
+
+ .. collapse:: parallel_2d.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/parallel/parallel_2d.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/parallel/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/`` `parallel <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/parallel>`_
+
+In ``parallel``, an example of how to run a 2D parallel simulation is presented.
+
+First, the mesh needs to be distributed among the processors. This is done with::
+
+ const auto & comm = Communicator::getStaticCommunicator();
+ Int prank = comm.whoAmI();
+ if (prank == 0) {
+ mesh.read("square_2d.msh");
+ }
+ mesh.distribute();
+
+Here ``prank`` designate the processor rank. The mesh is read only by processor 0 and then distributed among all the processors.
+All the prints are done only by processor 0. For instance::
+
+ if (prank == 0) {
+ std::cout << model.getMaterial(0) << std::endl;
+ }
+
+.. figure:: examples/c++/solid_mechanics_model/parallel/images/parallel.png
+ :align: center
+ :width: 60%
+
+ Displacement in the x direction.
+
+
diff --git a/examples/c++/solid_mechanics_model/parallel/images/parallel.png b/examples/c++/solid_mechanics_model/parallel/images/parallel.png
new file mode 100644
index 000000000..8d3b29cda
Binary files /dev/null and b/examples/c++/solid_mechanics_model/parallel/images/parallel.png differ
diff --git a/examples/parallel/material.dat b/examples/c++/solid_mechanics_model/parallel/material.dat
similarity index 100%
rename from examples/parallel/material.dat
rename to examples/c++/solid_mechanics_model/parallel/material.dat
diff --git a/examples/parallel/parallel_2d.cc b/examples/c++/solid_mechanics_model/parallel/parallel_2d.cc
similarity index 88%
rename from examples/parallel/parallel_2d.cc
rename to examples/c++/solid_mechanics_model/parallel/parallel_2d.cc
index 288abdb98..29c2cc719 100644
--- a/examples/parallel/parallel_2d.cc
+++ b/examples/c++/solid_mechanics_model/parallel/parallel_2d.cc
@@ -1,97 +1,99 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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);
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;
+ if (prank == 0) {
+ std::cout << model.getMaterial(0) << "\n";
+ }
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 (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;
+ std::cout << "Time Step = " << time_step << "s"
+ << "\n";
model.setTimeStep(time_step);
model.dump();
for (Int s = 1; s <= max_steps; ++s) {
model.solveStep();
- if (s % 200 == 0)
+ if (s % 200 == 0) {
model.dump();
+ }
- if (prank == 0 && s % 100 == 0)
- std::cout << "passing step " << s << "/" << max_steps << std::endl;
+ if (prank == 0 && s % 100 == 0) {
+ std::cout << "passing step " << s << "/" << max_steps << "\n";
+ }
}
- finalize();
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/parallel/square_2d.geo b/examples/c++/solid_mechanics_model/parallel/square_2d.geo
similarity index 100%
rename from examples/parallel/square_2d.geo
rename to examples/c++/solid_mechanics_model/parallel/square_2d.geo
diff --git a/examples/static/CMakeLists.txt b/examples/c++/solid_mechanics_model/static/CMakeLists.txt
similarity index 100%
rename from examples/static/CMakeLists.txt
rename to examples/c++/solid_mechanics_model/static/CMakeLists.txt
diff --git a/examples/c++/solid_mechanics_model/static/README.rst b/examples/c++/solid_mechanics_model/static/README.rst
new file mode 100644
index 000000000..67da794b1
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/static/README.rst
@@ -0,0 +1,40 @@
+Static test cases (2D)
+''''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: static.cc (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/static/static.cc
+ :language: c++
+ :lines: 20-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/c++/solid_mechanics_model/static/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/c++/solid_mechanics_model/`` `static <https://gitlab.com/akantu/akantu/-/blob/master/examples/c++/solid_mechanics_model/static>`_
+
+
+In ``static``, an example of how to solve a static problem is presented. The
+problem geometry is shown in :numref:`fig-ex-static`. The left and bottom side
+of a 2D plate are blocked with rollers and nodes from the left side are
+displaced upward by :math:`0.01\%` of the length of the plate.
+
+.. _fig-ex-static:
+.. figure:: examples/c++/solid_mechanics_model/static/images/static_BC.svg
+ :align: center
+
+ Boundary conditions for the static example.
+
+The solution for the static analysis is shown in :numref:`fig-ex-static_disp`.
+
+.. _fig-ex-static_disp:
+.. figure:: examples/c++/solid_mechanics_model/static/images/static_displ_mag.png
+ :align: center
+ :width: 60%
+
+ Solution of the static analysis: displacement magnitude.
diff --git a/examples/c++/solid_mechanics_model/static/images/static_BC.svg b/examples/c++/solid_mechanics_model/static/images/static_BC.svg
new file mode 100644
index 000000000..0e8a5d623
--- /dev/null
+++ b/examples/c++/solid_mechanics_model/static/images/static_BC.svg
@@ -0,0 +1,518 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="115.303mm"
+ height="99.26429mm"
+ viewBox="0 0 115.30301 99.26429"
+ version="1.1"
+ id="svg5"
+ xml:space="preserve"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="dessin_inkscape.svg"
+ inkscape:export-filename="static_BC.svg"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview7"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false"
+ inkscape:lockguides="true"
+ inkscape:zoom="1.829812"
+ inkscape:cx="368.6171"
+ inkscape:cy="301.67033"
+ inkscape:window-width="2560"
+ inkscape:window-height="1371"
+ inkscape:window-x="0"
+ inkscape:window-y="32"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g97" /><defs
+ id="defs2"><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient7100"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7098" /></linearGradient><marker
+ style="overflow:visible"
+ id="TriangleStart"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.189255"
+ markerHeight="3.687"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid"><path
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135"
+ transform="scale(0.5)" /></marker><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4804"
+ id="linearGradient4806"
+ x1="1202.173"
+ y1="480.5629"
+ x2="1204.2388"
+ y2="480.5629"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.5102399)" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4804"
+ id="linearGradient4826"
+ x1="1202.173"
+ y1="480.5629"
+ x2="1204.2388"
+ y2="480.5629"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(0,-2.5102399)" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4804"
+ id="linearGradient7102"
+ x1="1196.8698"
+ y1="125.8196"
+ x2="1209.5233"
+ y2="125.8196"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3271196,0,0.01220663,5.3559214,-1598.652,-589.49335)" /><linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4804"
+ id="linearGradient7136"
+ x1="1196.8698"
+ y1="125.8196"
+ x2="1209.5233"
+ y2="125.8196"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(2.3271196,0,0.01220663,5.3559214,-1598.652,-589.49335)" /></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-35.991445,-8.8315363)"><g
+ id="g97"
+ transform="matrix(0.14352268,0,0,0.11578455,-27.258384,1.4003671)"><circle
+ fill="#5a5a5a"
+ cx="516.78601"
+ cy="823.71399"
+ r="2"
+ id="circle81" /><circle
+ fill="#5a5a5a"
+ cx="1203.21"
+ cy="823.71399"
+ r="2"
+ id="circle83" /><circle
+ fill="#5a5a5a"
+ cx="1203.21"
+ cy="137.286"
+ r="2"
+ id="circle85" /><circle
+ fill="#5a5a5a"
+ cx="516.78601"
+ cy="137.286"
+ r="2"
+ id="circle87" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="516.786,823.714 1203.21,823.714 1203.21,137.286 516.786,137.286 516.786,823.714"
+ id="polyline89"
+ style="stroke-width:4.32861;stroke-dasharray:none" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1690,921"
+ id="polyline91" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1660,891"
+ id="polyline93" /><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1660,921"
+ id="polyline95" /><path
+ style="fill:url(#linearGradient4806);fill-opacity:1;stroke:url(#linearGradient4826);stroke-width:4.32861;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 1203.2009,135.00223 0.01,686.10083"
+ id="path1388" /><path
+ style="fill:url(#linearGradient7136);fill-opacity:1;stroke:url(#linearGradient7102);stroke-width:7.2575;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0.5;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
+ d="m 1202.9656,128.25252 -0.118,-48.63449"
+ id="path5554"
+ inkscape:transform-center-y="2.0254206"
+ inkscape:transform-center-x="-0.0051702646" /></g><g
+ id="g4256"
+ transform="matrix(0.23733616,0,0,0.27167982,10.209103,-49.889664)"><g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" /></g></g><g
+ id="g4256-36"
+ transform="matrix(0.23733616,0,0,0.27167982,10.467344,29.661108)"><g
+ id="g2882-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62" /></g></g><g
+ id="g4256-36-8"
+ transform="matrix(0,-0.23733616,0.27167982,0,-20.517226,132.70406)"><g
+ id="g2882-7-9"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4" /></g></g><g
+ id="g4256-36-8-4"
+ transform="matrix(0,-0.23733616,0.27167982,0,28.064012,132.70404)"><g
+ id="g2882-7-9-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7" /></g></g><g
+ id="g4256-36-8-5"
+ transform="matrix(0,-0.23733616,0.27167982,0,78.112869,132.70404)"><g
+ id="g2882-7-9-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5" /></g></g><g
+ id="g4256-36-6"
+ transform="matrix(0.23733616,0,0,0.27167982,10.302838,-10.270631)"><g
+ id="g2882-7-1"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-7"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-2"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-2" /></g></g></g></svg>
diff --git a/examples/c++/solid_mechanics_model/static/images/static_displ_mag.png b/examples/c++/solid_mechanics_model/static/images/static_displ_mag.png
new file mode 100644
index 000000000..0cb28283e
Binary files /dev/null and b/examples/c++/solid_mechanics_model/static/images/static_displ_mag.png differ
diff --git a/examples/static/material.dat b/examples/c++/solid_mechanics_model/static/material.dat
similarity index 100%
rename from examples/static/material.dat
rename to examples/c++/solid_mechanics_model/static/material.dat
diff --git a/examples/static/square.geo b/examples/c++/solid_mechanics_model/static/square.geo
similarity index 93%
rename from examples/static/square.geo
rename to examples/c++/solid_mechanics_model/static/square.geo
index 3c299d0ec..35b91b123 100644
--- a/examples/static/square.geo
+++ b/examples/c++/solid_mechanics_model/static/square.geo
@@ -1,29 +1,29 @@
// Mesh size
h = 0.005;
// Dimensions of the square
Lx = 0.01;
Ly = 0.01;
// ------------------------------------------
// Geometry
// ------------------------------------------
Point(1) = { 0.0, 0.0, 0.0, h};
Point(2) = { Lx, 0.0, 0.0, h};
Point(3) = { Lx, Ly, 0.0, h};
Point(4) = { 0.0, Ly, 0.0, h};
Line(1) = {1, 2};
Line(2) = {2, 3};
Line(3) = {3, 4};
Line(4) = {4, 1};
Line Loop(1) = {1:4};
Plane Surface(1) = {1};
Physical Surface(1) = {1};
Physical Line("Fixed_y") = {1};
Physical Line("Fixed_x") = {4};
-Physical Line("Traction") = {2};
+Physical Line("Displacement") = {2};
Physical Line("Free") = {3};
diff --git a/examples/static/static.cc b/examples/c++/solid_mechanics_model/static/static.cc
similarity index 90%
rename from examples/static/static.cc
rename to examples/c++/solid_mechanics_model/static/static.cc
index ddc9059a0..d63bc23c2 100644
--- a/examples/static/static.cc
+++ b/examples/c++/solid_mechanics_model/static/static.cc
@@ -1,69 +1,67 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 Int spatial_dimension = 2;
Mesh mesh(spatial_dimension);
mesh.read("square.msh");
SolidMechanicsModel model(mesh);
/// model initialization
model.initFull(_analysis_method = _static);
+ /// configure dumper
model.setBaseName("static");
model.addDumpFieldVector("displacement");
model.addDumpField("external_force");
model.addDumpField("internal_force");
+ model.addDumpField("blocked_dofs");
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.applyBC(BC::Dirichlet::FixedValue(0.0001, _x), "Displacement");
model.dump();
+ /// set the limits for the Newton-Raphson solver
auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 2);
solver.set("threshold", 2e-4);
solver.set("convergence_type", SolveConvergenceCriteria::_solution);
+ /// static solve
model.solveStep();
model.dump();
- finalize();
-
- return EXIT_SUCCESS;
+ return 0;
}
diff --git a/examples/structural_mechanics/CMakeLists.txt b/examples/c++/structural_mechanics_model/CMakeLists.txt
similarity index 100%
rename from examples/structural_mechanics/CMakeLists.txt
rename to examples/c++/structural_mechanics_model/CMakeLists.txt
diff --git a/examples/structural_mechanics/bernoulli_beam_2_example.cc b/examples/c++/structural_mechanics_model/bernoulli_beam_2_example.cc
similarity index 100%
rename from examples/structural_mechanics/bernoulli_beam_2_example.cc
rename to examples/c++/structural_mechanics_model/bernoulli_beam_2_example.cc
diff --git a/examples/heat_transfer/material.dat b/examples/heat_transfer/material.dat
deleted file mode 100644
index f2c0c3733..000000000
--- a/examples/heat_transfer/material.dat
+++ /dev/null
@@ -1,10 +0,0 @@
-model heat_transfer_model [
- density = 8940
- capacity = 385
- conductivity = [[401, 0, 0],\
- [0, 401, 0],\
- [0, 0, 401]]
-]
-
-
-
diff --git a/examples/python/CMakeLists.txt b/examples/python/CMakeLists.txt
index a8e77e062..98e5e8a58 100644
--- a/examples/python/CMakeLists.txt
+++ b/examples/python/CMakeLists.txt
@@ -1,41 +1,35 @@
#===============================================================================
# Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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_subdirectory(custom-material)
-add_subdirectory(dynamics)
-add_subdirectory(eigen_modes)
-add_subdirectory(plate-hole)
-add_subdirectory(stiffness_matrix)
-
-add_example(structural_mechanics "structural mechanics example in python"
+add_example(structural_mechanics_model "structural mechanics example in python"
PACKAGE structural_mechanics)
-add_example(fragmentation "example of fragmentation in python"
- PACKAGE cohesive_element)
-add_example(phase-field "phase-field example in python"
+add_example(phase_field_model "phase-field example in python"
PACKAGE phase_field)
-add_example(cohesive "cohesive element examples in python"
+add_example(solid_mechanics_cohesive_model "cohesive element examples in python"
PACKAGE cohesive_element)
-add_example(contact-mechanics "contact mechanics example in python"
+add_example(solid_mechanics_model "solid_mechanics_model in python"
+ PACKAGE solid_mechanics)
+add_example(contact_mechanics_model "contact mechanics example in python"
PACKAGE contact_mechanics)
package_add_files_to_package(
examples/python/README.rst
)
diff --git a/examples/python/README.rst b/examples/python/README.rst
index 57361e88d..d003011bb 100644
--- a/examples/python/README.rst
+++ b/examples/python/README.rst
@@ -1,8 +1,29 @@
-In order to use the Akantu examples using the python mode, one has to source
-the file ``akantu_environement.sh``:
+Python examples
+---------------
-| > source <AKANTU_BUILD_DIR>/akantu_environement.sh
+To run simulations in Python using Akantu, you first need to import the module:
-or for an installed akantu version:
+.. code-block:: python
-| > source <AKANTU_INSTALL_DIR>/share/akantu<VERSION>/akantu_environement.sh
+ import akantu as aka
+
+The functions in Python are mostly the same as in C++.
+
+The initiation differs. While in C++ a function is initialized using ``initialize("material.dat", argc, argv);``, in Python you should do:
+
+.. code-block:: python
+
+ aka.parseInput('material.dat')
+
+The creation and loading of the mesh is done with:
+
+.. code-block:: python
+
+ mesh = aka.Mesh(spatial_dimension)
+ mesh.read('mesh.msh')
+
+
+.. include:: examples/python/solid_mechanics_model/README.rst
+.. include:: examples/python/solid_mechanics_cohesive_model/README.rst
+.. include:: examples/python/contact_mechanics_model/README.rst
+.. include:: examples/python/phase_field_model/README.rst
diff --git a/examples/python/contact-mechanics/CMakeLists.txt b/examples/python/contact_mechanics_model/CMakeLists.txt
similarity index 100%
rename from examples/python/contact-mechanics/CMakeLists.txt
rename to examples/python/contact_mechanics_model/CMakeLists.txt
diff --git a/examples/python/contact_mechanics_model/README.rst b/examples/python/contact_mechanics_model/README.rst
new file mode 100644
index 000000000..1dfe34422
--- /dev/null
+++ b/examples/python/contact_mechanics_model/README.rst
@@ -0,0 +1,30 @@
+Contact mechanics model (2D)
+````````````````````````````
+:Sources:
+
+ .. collapse:: compression.py (click to expand)
+
+ .. literalinclude:: examples/python/contact_mechanics_model/compression.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: compression.dat (click to expand)
+
+ .. literalinclude:: examples/python/contact_mechanics_model/compression.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/`` `contact_mechanics_model <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/contact_mechanics_model>`_
+
+In `compression.py` it is shown how to couple the Solid Mechanics Model with the Contact Mechanics Model. The example
+simulate the contact betweem two blocks.
+
+.. figure:: examples/python/contact_mechanics_model/images/compression.svg
+ :align: center
+ :width: 25%
+
+.. figure:: examples/python/contact_mechanics_model/images/contact.gif
+ :align: center
+ :width: 50%
+
diff --git a/examples/python/contact-mechanics/compression.dat b/examples/python/contact_mechanics_model/compression.dat
similarity index 100%
rename from examples/python/contact-mechanics/compression.dat
rename to examples/python/contact_mechanics_model/compression.dat
diff --git a/examples/python/contact-mechanics/compression.geo b/examples/python/contact_mechanics_model/compression.geo
similarity index 100%
rename from examples/python/contact-mechanics/compression.geo
rename to examples/python/contact_mechanics_model/compression.geo
diff --git a/examples/python/contact-mechanics/compression.py b/examples/python/contact_mechanics_model/compression.py
similarity index 100%
rename from examples/python/contact-mechanics/compression.py
rename to examples/python/contact_mechanics_model/compression.py
diff --git a/examples/python/contact-mechanics/detection-explicit.dat b/examples/python/contact_mechanics_model/detection-explicit.dat
similarity index 100%
rename from examples/python/contact-mechanics/detection-explicit.dat
rename to examples/python/contact_mechanics_model/detection-explicit.dat
diff --git a/examples/python/contact-mechanics/detection-explicit.msh b/examples/python/contact_mechanics_model/detection-explicit.msh
similarity index 100%
rename from examples/python/contact-mechanics/detection-explicit.msh
rename to examples/python/contact_mechanics_model/detection-explicit.msh
diff --git a/examples/python/contact-mechanics/detection-explicit.py b/examples/python/contact_mechanics_model/detection-explicit.py
similarity index 100%
rename from examples/python/contact-mechanics/detection-explicit.py
rename to examples/python/contact_mechanics_model/detection-explicit.py
diff --git a/examples/python/contact_mechanics_model/images/compression.svg b/examples/python/contact_mechanics_model/images/compression.svg
new file mode 100644
index 000000000..7fee46b9e
--- /dev/null
+++ b/examples/python/contact_mechanics_model/images/compression.svg
@@ -0,0 +1,1033 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="64.156868mm"
+ height="114.62799mm"
+ viewBox="0 0 64.156869 114.62799"
+ version="1.1"
+ id="svg5"
+ xml:space="preserve"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview7"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false" /><defs
+ id="defs2"><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-0" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-7"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-5" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9-8" /></marker><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-27"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-09" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-36"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-0" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-6"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-6"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-1" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0-8"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9-7" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-3-92"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-6-0" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-0-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-6-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-2-7"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-6-5" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-2-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-0-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-2-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-3-8" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-7-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-5-7" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-9-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-2-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0-2-1"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9-8-2" /></marker></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-20.411667,-6.789129)"><g
+ id="g5444"><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1414.46,187.571 945.536,187.571 945.536,656.5 1414.46,656.5 1414.46,187.571"
+ id="polyline200"
+ transform="matrix(0.10768149,0,0,0.10768149,-74.574687,-6.5396669)"
+ style="stroke:#000000;stroke-width:5.61842;stroke-dasharray:none" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="945.536,656.5 945.536,1125.43 1414.46,1125.43 1414.46,656.5"
+ id="polyline202"
+ transform="matrix(0.10768149,0,0,0.10768149,-74.574687,-6.5396669)"
+ style="stroke:#000000;stroke-width:5.61842;stroke-dasharray:none" /><g
+ id="g2945"
+ transform="translate(-79.90421,104.7751)"><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3)"
+ d="M 108.31546,16.342062 V 11.028596"
+ id="path857-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5)"
+ d="M 112.16357,16.342062 V 11.028596"
+ id="path857-7-5"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6)"
+ d="M 116.32787,16.342062 V 11.028596"
+ id="path857-7-2"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9)"
+ d="M 120.17597,16.342062 V 11.028596"
+ id="path857-7-5-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0)"
+ d="M 124.1588,16.469102 V 11.155636"
+ id="path857-7-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-3)"
+ d="M 128.0069,16.469102 V 11.155636"
+ id="path857-7-5-8"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-0)"
+ d="M 132.1712,16.469102 V 11.155636"
+ id="path857-7-2-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-2)"
+ d="M 136.0193,16.469102 V 11.155636"
+ id="path857-7-5-7-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-2)"
+ d="M 140.44925,16.514978 V 11.201513"
+ id="path857-7-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-2)"
+ d="M 144.29735,16.514978 V 11.201513"
+ id="path857-7-5-3"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-7)"
+ d="M 148.46164,16.514978 V 11.201513"
+ id="path857-7-2-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-9)"
+ d="M 152.30975,16.514978 V 11.201513"
+ id="path857-7-5-7-94"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0-2)"
+ d="M 156.29258,16.642019 V 11.328553"
+ id="path857-7-1-7"
+ sodipodi:nodetypes="cc" /></g><g
+ id="g2945-9"
+ transform="rotate(180,92.530848,11.715574)"><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-27)"
+ d="M 108.31546,16.342062 V 11.028596"
+ id="path857-7-3"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-36)"
+ d="M 112.16357,16.342062 V 11.028596"
+ id="path857-7-5-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-6)"
+ d="M 116.32787,16.342062 V 11.028596"
+ id="path857-7-2-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-6)"
+ d="M 120.17597,16.342062 V 11.028596"
+ id="path857-7-5-7-4"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0-8)"
+ d="M 124.1588,16.469102 V 11.155636"
+ id="path857-7-1-78"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-3-92)"
+ d="M 128.0069,16.469102 V 11.155636"
+ id="path857-7-5-8-4"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-0-2)"
+ d="M 132.1712,16.469102 V 11.155636"
+ id="path857-7-2-7-5"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-2-7)"
+ d="M 136.0193,16.469102 V 11.155636"
+ id="path857-7-5-7-9-0"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-2-9)"
+ d="M 140.44925,16.514978 V 11.201513"
+ id="path857-7-9-3"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-2-2)"
+ d="M 144.29735,16.514978 V 11.201513"
+ id="path857-7-5-3-6"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-7-9)"
+ d="M 148.46164,16.514978 V 11.201513"
+ id="path857-7-2-1-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-9-3)"
+ d="M 152.30975,16.514978 V 11.201513"
+ id="path857-7-5-7-94-0"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.232811px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0-2-1)"
+ d="M 156.29258,16.642019 V 11.328553"
+ id="path857-7-1-7-6"
+ sodipodi:nodetypes="cc" /></g><g
+ id="g9336"
+ transform="matrix(0,-0.73078625,0.87364458,0,8.8043389,129.92959)"><g
+ id="g4256-36-8"
+ transform="matrix(0,-0.17201065,0.1969014,0,-27.647856,105.40788)"><g
+ id="g2882-7-9"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4" /></g></g><g
+ id="g4256-36-8-4"
+ transform="matrix(0,-0.17201065,0.1969014,0,6.894128,105.40788)"><g
+ id="g2882-7-9-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7" /></g></g><g
+ id="g4256-36-8-5"
+ transform="matrix(0,-0.17201065,0.1969014,0,41.436112,105.40788)"><g
+ id="g2882-7-9-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5" /></g></g><g
+ id="g4256-36-8-5-6"
+ transform="matrix(0,-0.17201065,0.1969014,0,75.978096,105.40788)"><g
+ id="g2882-7-9-0-2"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6" /></g></g><g
+ id="g4256-36-8-5-6-1"
+ transform="matrix(0,-0.17201065,0.1969014,0,110.52008,105.40788)"><g
+ id="g2882-7-9-0-2-8"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8" /></g></g></g><g
+ id="g9336-9"
+ transform="matrix(0,0.73078625,-0.87364458,0,96.175864,-1.8400377)"><g
+ id="g4256-36-8-7"
+ transform="matrix(0,-0.17201065,0.1969014,0,-27.647856,105.40788)"><g
+ id="g2882-7-9-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-61"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-47" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-50" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-6" /></g></g><g
+ id="g4256-36-8-4-1"
+ transform="matrix(0,-0.17201065,0.1969014,0,6.894128,105.40788)"><g
+ id="g2882-7-9-7-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7-1"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7-5" /></g></g><g
+ id="g4256-36-8-5-69"
+ transform="matrix(0,-0.17201065,0.1969014,0,41.436112,105.40788)"><g
+ id="g2882-7-9-0-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-7" /></g></g><g
+ id="g4256-36-8-5-6-8"
+ transform="matrix(0,-0.17201065,0.1969014,0,75.978096,105.40788)"><g
+ id="g2882-7-9-0-2-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-4"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-9" /></g></g><g
+ id="g4256-36-8-5-6-1-2"
+ transform="matrix(0,-0.17201065,0.1969014,0,110.52008,105.40788)"><g
+ id="g2882-7-9-0-2-8-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0-5"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8-7" /></g></g></g></g></g></svg>
diff --git a/examples/python/contact_mechanics_model/images/contact.gif b/examples/python/contact_mechanics_model/images/contact.gif
new file mode 100644
index 000000000..39e1312c4
Binary files /dev/null and b/examples/python/contact_mechanics_model/images/contact.gif differ
diff --git a/examples/python/phase-field/CMakeLists.txt b/examples/python/phase_field_model/CMakeLists.txt
similarity index 100%
rename from examples/python/phase-field/CMakeLists.txt
rename to examples/python/phase_field_model/CMakeLists.txt
diff --git a/examples/python/phase_field_model/README.rst b/examples/python/phase_field_model/README.rst
new file mode 100644
index 000000000..3a0311731
--- /dev/null
+++ b/examples/python/phase_field_model/README.rst
@@ -0,0 +1,71 @@
+Phase-field model (2D)
+``````````````````````
+
+static
+''''''
+
+:Sources:
+
+ .. collapse:: phasefield-static.py (click to expand)
+
+ .. literalinclude:: examples/python/phase_field_model/phasefield-static.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material_static.dat (click to expand)
+
+ .. literalinclude:: examples/python/phase_field_model/material_static.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/`` `phase_field_model <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/phase_field_model>`_
+
+
+`phasefield-static.py` shows how to setup a static phase-field fracture simulation. An imposed displacement is imposed on the top of a notched square plate.
+
+.. figure:: examples/python/phase_field_model/images/phasefield-static-geo.svg
+ :align: center
+ :width: 50%
+
+ Notched plate with boundary conditions and imposed displacement.
+
+In static simulations, we use loading steps to apply the displacement incrementally. At each time step, the solvers of the solid mechanics model and the phase-field model are called alternately until convergence is reached.
+
+.. figure:: examples/python/phase_field_model/images/phasefield-static.png
+ :align: center
+ :width: 50%
+
+ Damage field after a few iterations.
+
+dynamic
+'''''''
+
+:Sources:
+
+ .. collapse:: phasefield-dynamic.py (click to expand)
+
+ .. literalinclude:: examples/python/phase_field_model/phasefield-dynamic.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/phase_field_model/material.dat
+ :language: text
+
+`phasefield-dynamic.py` shows how to setup a dynamic phase-field fracture simulation. A notched plate is pre-strained in mode I using Dirichlet BC and a static solve. The simulation is then continued in dynamic using an explicit Neumark scheme.
+
+.. figure:: examples/python/phase_field_model/images/phasefield-dynamic-geo.svg
+ :align: center
+ :width: 80%
+
+ Notched plate with boundary conditions and imposed displacement.
+
+At each time step, each solver is called once to find the displacement field and the damage field.
+
+.. figure:: examples/python/phase_field_model/images/phasefield-dynamic.png
+ :align: center
+ :width: 80%
+
+ Crack propagation and branching.
diff --git a/examples/python/phase_field_model/images/phasefield-dynamic-geo.svg b/examples/python/phase_field_model/images/phasefield-dynamic-geo.svg
new file mode 100644
index 000000000..f64ba76f3
--- /dev/null
+++ b/examples/python/phase_field_model/images/phasefield-dynamic-geo.svg
@@ -0,0 +1,1205 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="1318.2913pt"
+ height="725.95184pt"
+ viewBox="0 0 1318.2913 725.95184"
+ version="1.1"
+ id="svg50"
+ sodipodi:docname="phasefield-dynamic-geo.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <sodipodi:namedview
+ id="namedview52"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="pt"
+ showgrid="true"
+ inkscape:zoom="0.89527792"
+ inkscape:cx="786.90648"
+ inkscape:cy="447.90561"
+ inkscape:window-width="2560"
+ inkscape:window-height="1371"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g48">
+ <inkscape:grid
+ type="xygrid"
+ id="grid6767"
+ originx="-136.65901"
+ originy="-94.808433" />
+ </sodipodi:namedview>
+ <title
+ id="title2">phasefield-dynamic-geo</title>
+ <desc
+ id="desc4">
+Creator: GL2PS 1.4.2, (C) 1999-2020 C. Geuzaine
+For: Gmsh
+CreationDate: Wed Sep 27 14:44:55 2023
+</desc>
+ <defs
+ id="defs6">
+ <marker
+ style="overflow:visible"
+ id="TriangleStart"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-8"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-1" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-3"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-0" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-3-4"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-0-4" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-7"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-6" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-8-3"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-1-1" />
+ </marker>
+ </defs>
+ <g
+ id="g48"
+ transform="translate(-136.65901,-94.808434)">
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="378.161,515 232.714,515 232.714,805.893 1396.29,805.893 1396.29,515"
+ id="polyline34-3"
+ style="fill:#b4b4b4;fill-opacity:1;stroke:none"
+ transform="translate(-17.999674,-347.23886)"
+ inkscape:transform-center-x="-154.91697"
+ inkscape:transform-center-y="226.65776" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="232.714,515 378.161,515"
+ id="polyline24"
+ style="fill:#000000;fill-opacity:1"
+ transform="translate(-18.284599,-56.894676)" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="232.714,224.107 232.714,515"
+ id="polyline26"
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(-18.284599,-56.894676)" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1396.29,224.107 232.714,224.107"
+ id="polyline28"
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(-18.284599,-56.894676)" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 214.98538,166.89781 H 1376.7384"
+ id="path11333"
+ sodipodi:nodetypes="cc" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1396.29,515 1396.29,224.107"
+ id="polyline30"
+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(-18.284599,-56.894676)" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="378.161,515 1396.29,515"
+ id="polyline32"
+ style="fill:#000000;fill-opacity:1"
+ transform="translate(-18.284599,-56.894676)" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="378.161,515 232.714,515 232.714,805.893 1396.29,805.893 1396.29,515"
+ id="polyline34"
+ style="fill:#b4b4b4;fill-opacity:1;stroke:#000000;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="translate(-18.284599,-56.894676)" />
+ <path
+ style="fill:none;fill-opacity:1;stroke:#ff0000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 210.62984,748.023 H 1372.3829"
+ id="path11333-5"
+ sodipodi:nodetypes="cc" />
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="378.161,515 232.714,515 232.714,805.893 1396.29,805.893 1396.29,515"
+ id="polyline34-3-6"
+ style="fill:#b4b4b4;fill-opacity:1;stroke:none"
+ transform="matrix(0.87435003,0,0,1,155.16751,-214.80756)"
+ inkscape:transform-center-x="-135.45166"
+ inkscape:transform-center-y="226.65776" />
+ <g
+ id="g4256"
+ transform="matrix(1.7488444,0,0,1.7488444,-52.794901,-263.23462)">
+ <g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" />
+ </g>
+ </g>
+ <g
+ id="g4256-7"
+ transform="matrix(1.7488444,0,0,1.7488444,-53.321749,316.09077)">
+ <g
+ id="g2882-5"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-0"
+ transform="matrix(1.7488444,0,0,1.7488444,-53.004327,114.8919)">
+ <g
+ id="g2882-5-6"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-2"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-1"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-8"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-7"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-9"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-5" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-9"
+ transform="matrix(1.7488444,0,0,1.7488444,-52.49711,-58.174339)">
+ <g
+ id="g2882-5-2"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-28"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-9"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-7"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-1"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-29" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-7" />
+ </g>
+ </g>
+ <g
+ id="g4256-8"
+ transform="matrix(-1.7488444,0,0,-1.7488444,1644.4041,1179.1257)">
+ <g
+ id="g2882-4"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-0"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-0"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-1" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-5"
+ transform="matrix(-1.7488444,0,0,-1.7488444,1644.931,599.8003)">
+ <g
+ id="g2882-5-5"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-4"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-7"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-6"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-5"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-69"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-3"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-4" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-5-8"
+ transform="matrix(-1.7488444,0,0,-1.7488444,855.28991,599.0591)">
+ <g
+ id="g2882-5-5-7"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-4-1"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-7-7"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-6-2"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-5-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-69-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-3-2"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-7-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-4-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-2-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-5-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-4-5" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-5-8-9"
+ transform="matrix(-1.7488444,0,0,-1.7488444,1299.3123,598.26065)">
+ <g
+ id="g2882-5-5-7-4"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-4-1-9"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-7-7-0"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-6-2-9"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-5-7-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-69-2-7"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-3-2-7"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-7-6-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-4-1-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-0-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-2-6-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-5-1-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-4-5-7" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-5-8-6"
+ transform="matrix(-1.7488444,0,0,-1.7488444,853.47368,1180.7864)">
+ <g
+ id="g2882-5-5-7-7"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-4-1-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-7-7-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-6-2-5"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-5-7-6"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-69-2-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-3-2-9"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-7-6-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-4-1-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-0-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-2-6-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-5-1-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-4-5-3" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-5-8-9-9"
+ transform="matrix(-1.7488444,0,0,-1.7488444,1297.4961,1179.988)">
+ <g
+ id="g2882-5-5-7-4-0"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-4-1-9-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-7-7-0-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-6-2-9-5"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-5-7-1-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-69-2-7-9"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-3-2-7-6"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-7-6-1-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-4-1-1-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-0-5-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-2-6-9-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-5-1-7-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-4-5-7-1" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-0-7"
+ transform="matrix(-1.7488444,0,0,-1.7488444,1644.6136,800.99917)">
+ <g
+ id="g2882-5-6-4"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-2-4"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-6-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-1-0"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-8-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-7-8"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-9-6"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-2-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-0-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-2-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-3-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-7-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-5-4" />
+ </g>
+ </g>
+ <g
+ id="g4256-7-9-9"
+ transform="matrix(-1.7488444,0,0,-1.7488444,1644.1064,974.06538)">
+ <g
+ id="g2882-5-2-2"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-3-28-0"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-9-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6-7-8"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-2-3-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9-6-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-1-1-6"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-2-29-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-7-3-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-1-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-9-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-4-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-7-4" />
+ </g>
+ </g>
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart)"
+ d="m 412.13961,108.46511 v 41.86681 19.21541"
+ id="path11335"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-8)"
+ d="m 1211.7909,105.89302 v 41.86681 19.2154"
+ id="path11335-0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-3)"
+ d="m 815.28672,107.12094 v 41.86681 19.2154"
+ id="path11335-44"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-7)"
+ d="m 1211.9414,807.10362 v -41.86681 -19.2154"
+ id="path11335-7"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-8-3)"
+ d="M 412.29014,809.67571 V 767.8089 748.5935"
+ id="path11335-0-5"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-3-4)"
+ d="M 808.79433,806.94779 V 765.08098 745.86559"
+ id="path11335-44-9"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <metadata
+ id="metadata12733">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:title>phasefield-dynamic-geo</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/examples/python/phase_field_model/images/phasefield-dynamic.png b/examples/python/phase_field_model/images/phasefield-dynamic.png
new file mode 100644
index 000000000..7b28d1329
Binary files /dev/null and b/examples/python/phase_field_model/images/phasefield-dynamic.png differ
diff --git a/examples/python/phase_field_model/images/phasefield-static-geo.svg b/examples/python/phase_field_model/images/phasefield-static-geo.svg
new file mode 100644
index 000000000..056162b92
--- /dev/null
+++ b/examples/python/phase_field_model/images/phasefield-static-geo.svg
@@ -0,0 +1,753 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ width="835.25348pt"
+ height="871.4165pt"
+ viewBox="0 0 835.25348 871.4165"
+ version="1.1"
+ id="svg40"
+ sodipodi:docname="phasefield-static-geo.svg"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <sodipodi:namedview
+ id="namedview42"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:showpageshadow="2"
+ inkscape:pageopacity="0.0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1"
+ inkscape:document-units="pt"
+ showgrid="true"
+ inkscape:zoom="0.63305709"
+ inkscape:cx="259.06036"
+ inkscape:cy="565.50982"
+ inkscape:window-width="2560"
+ inkscape:window-height="1371"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="g38">
+ <inkscape:grid
+ type="xygrid"
+ id="grid9425"
+ originx="-366.46895"
+ originy="-99.915513" />
+ </sodipodi:namedview>
+ <title
+ id="title2">phasefield-static-geo</title>
+ <desc
+ id="desc4">
+Creator: GL2PS 1.4.2, (C) 1999-2020 C. Geuzaine
+For: Gmsh
+CreationDate: Fri Sep 22 17:29:30 2023
+</desc>
+ <defs
+ id="defs6">
+ <marker
+ style="overflow:visible"
+ id="TriangleStart"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-7"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-2" />
+ </marker>
+ <marker
+ style="overflow:visible"
+ id="TriangleStart-6"
+ refX="0"
+ refY="0"
+ orient="auto-start-reverse"
+ inkscape:stockid="TriangleStart"
+ markerWidth="3.3239999"
+ markerHeight="3.8427744"
+ viewBox="0 0 5.3244081 6.1553851"
+ inkscape:isstock="true"
+ inkscape:collect="always"
+ preserveAspectRatio="xMidYMid">
+ <path
+ transform="scale(0.5)"
+ style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt"
+ d="M 5.77,0 -2.88,5 V -5 Z"
+ id="path135-1" />
+ </marker>
+ </defs>
+ <g
+ id="g38"
+ transform="translate(-366.46894,-99.915514)">
+ <polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="446.643,882.857 1182.36,882.857 1182.36,515 1182.36,147.143 446.643,147.143 446.643,514.264 814.5,515 446.643,515.736 446.643,882.857"
+ id="polyline24"
+ style="fill:#b4b4b4;fill-opacity:1;stroke:#060606;stroke-width:4;stroke-dasharray:none;stroke-opacity:1"
+ transform="matrix(0.98216964,0,0,0.98216964,5.4036939,27.427895)" />
+ <g
+ id="g4256"
+ transform="matrix(1.7488444,0,0,1.7488444,177.87569,-258.84208)">
+ <g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" />
+ </g>
+ </g>
+ <g
+ id="g4256-3"
+ transform="matrix(1.7488444,0,0,1.7488444,176.48818,460.17543)">
+ <g
+ id="g2882-6"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-56"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-9"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6" />
+ </g>
+ </g>
+ <g
+ id="g4256-3-3"
+ transform="matrix(0,-1.7488444,1.7488444,0,11.128075,1158.3219)">
+ <g
+ id="g2882-6-6"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-7-1"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-0"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3-6"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-56-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-9-0"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-6" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-7" />
+ </g>
+ </g>
+ <g
+ id="g4256-3-3-6"
+ transform="matrix(0,-1.7488444,1.7488444,0,734.21228,1161.3128)">
+ <g
+ id="g2882-6-6-5"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-7-1-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-0-9"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3-6-3"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-56-3-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-4"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-9-0-5"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-6-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-1-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-5-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-4-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-7-4" />
+ </g>
+ </g>
+ <g
+ id="g4256-3-3-3"
+ transform="matrix(0,-1.7488444,1.7488444,0,248.9514,1160.9594)">
+ <g
+ id="g2882-6-6-0"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-7-1-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-0-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3-6-6"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-56-3-8"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-8"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-9-0-4"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-6-3" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-1-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-49" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-5-2" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-4-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-7-6" />
+ </g>
+ </g>
+ <g
+ id="g4256-3-3-8"
+ transform="matrix(0,-1.7488444,1.7488444,0,492.72389,1160.9594)">
+ <g
+ id="g2882-6-6-9"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-7-1-2"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-5-0-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-3-6-64"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-56-3-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-9-0-0"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-6-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-1-8" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-0-5-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-9-5-1" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-3-4-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-6-7-2" />
+ </g>
+ </g>
+ <g
+ id="g4256-0"
+ transform="matrix(1.7488444,0,0,1.7488444,176.83874,-4.9368783)">
+ <g
+ id="g2882-62"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-1"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-8"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-9"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-2"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-0" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-23" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-7" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-9" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-2" />
+ </g>
+ </g>
+ <g
+ id="g4256-2"
+ transform="matrix(1.7488444,0,0,1.7488444,177.43899,203.93706)">
+ <g
+ id="g2882-8"
+ transform="translate(-58.667089,88.9002)">
+ <path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-9"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-73"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" />
+ <g
+ id="g2875-6"
+ transform="translate(7.5,-0.54516576)">
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" />
+ <circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-29"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" />
+ </g>
+ </g>
+ <g
+ id="g4241-3"
+ transform="translate(18,-7.5)">
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-19" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-78" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-4" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-5" />
+ <path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-0" />
+ </g>
+ </g>
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="M 443.90785,172.65064 H 1166.8874"
+ id="path11333" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart)"
+ d="m 535.31518,111.0001 v 41.86681 19.2154"
+ id="path11335"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-7)"
+ d="M 811.86054,113.17079 V 155.0376 174.253"
+ id="path11335-2"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#ff0000;stroke-width:5;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#TriangleStart-6)"
+ d="m 1072.8032,112.20217 v 41.86681 19.2154"
+ id="path11335-0"
+ sodipodi:nodetypes="ccc" />
+ </g>
+ <metadata
+ id="metadata1714">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:title>phasefield-static-geo</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+</svg>
diff --git a/examples/python/phase_field_model/images/phasefield-static.png b/examples/python/phase_field_model/images/phasefield-static.png
new file mode 100644
index 000000000..05bfd051e
Binary files /dev/null and b/examples/python/phase_field_model/images/phasefield-static.png differ
diff --git a/examples/python/phase-field/material.dat b/examples/python/phase_field_model/material.dat
similarity index 100%
rename from examples/python/phase-field/material.dat
rename to examples/python/phase_field_model/material.dat
diff --git a/examples/python/phase-field/material_static.dat b/examples/python/phase_field_model/material_static.dat
similarity index 100%
rename from examples/python/phase-field/material_static.dat
rename to examples/python/phase_field_model/material_static.dat
diff --git a/examples/python/phase-field/phasefield-dynamic.py b/examples/python/phase_field_model/phasefield-dynamic.py
similarity index 85%
rename from examples/python/phase-field/phasefield-dynamic.py
rename to examples/python/phase_field_model/phasefield-dynamic.py
index 49b9e855f..b1ae5731f 100644
--- a/examples/python/phase-field/phasefield-dynamic.py
+++ b/examples/python/phase_field_model/phasefield-dynamic.py
@@ -1,103 +1,91 @@
#!/usr/bin/env python
# coding: utf-8
__copyright__ = (
"Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)"
"Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)"
)
__license__ = "LGPLv3"
import akantu as aka
# reading material file
aka.parseInput('material.dat')
# creating mesh
spatial_dimension = 2
mesh = aka.Mesh(spatial_dimension)
mesh.read('plate.msh')
model = aka.CouplerSolidPhaseField(mesh)
solid = model.getSolidMechanicsModel()
phase = model.getPhaseFieldModel()
-# initializing the Solid Mechanics Model with implicit solver for static resolution
+# initializing the Solid Mechanics Model with implicit solver for static
+# resolution
solid.initFull(_analysis_method=aka._static)
solver = solid.getNonLinearSolver('static')
solver.set('max_iterations', 100)
solver.set('threshold', 1e-10)
solver.set("convergence_type", aka.SolveConvergenceCriteria.residual)
# adding another solver dynamic/quasi-static resolution (explicit Newmark with
# lumped mass)
solid.initNewSolver(aka._explicit_lumped_mass)
-# initializing the PhaseField Model with linear implicit solver for static resolution
+# initializing the PhaseField Model with linear implicit solver for static
+# resolution
phase.initFull(_analysis_method=aka._static)
-# initializing the PhaseField Model with Newton Raphson implicit solver for static resolution
+# initializing the PhaseField Model with Newton Raphson implicit solver for
+# static resolution
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-3)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
# Initialization for bulk vizualisation
solid.setBaseName('plate')
solid.addDumpFieldVector('displacement')
solid.addDumpFieldVector('external_force')
solid.addDumpFieldVector('velocity')
solid.addDumpField('strain')
solid.addDumpField('stress')
solid.addDumpField('damage')
solid.addDumpField('blocked_dofs')
-
-class FixedDamage (aka.DirichletFunctor):
- '''
- Fix the damage to 0
- '''
- def __init__(self, axis):
- super().__init__(axis)
- self.axis = axis
-
- def __call__(self, node, flags, dam, coord):
- # sets the blocked dofs vector to true in the desired axis
- flags[int(self.axis)] = True
- dam[int(self.axis)] = 0.0
-
-
-# Dirichlet
+# Dirichlet BC
solid.applyBC(aka.FixedValue(0., aka._x), 'top')
solid.applyBC(aka.FixedValue(0., aka._x), 'bottom')
solid.applyBC(aka.FixedValue(0., aka._x), 'left')
solid.applyBC(aka.FixedValue(0., aka._x), 'right')
-
+# Pre-strain
solid.applyBC(aka.FixedValue(0.06e-3, aka._y), 'top')
solid.applyBC(aka.FixedValue(-0.06e-3, aka._y), 'bottom')
-
+# Apply pre-strain by solving static problem
solid.solveStep('static')
solid.dump()
# #### **Damped dynamics resolution**
solid.setTimeStep(solid.getStableTimeStep()*0.8)
# set maximum number of iteration
maxsteps = 1000
# solve using staggered scheme
for i in range(0, maxsteps):
if i % 100 == 0:
print('step {0}/{1}'.format(i, maxsteps))
model.solve('explicit_lumped', '')
if i % 100 == 0:
model.dump()
diff --git a/examples/python/phase-field/phasefield-static.py b/examples/python/phase_field_model/phasefield-static.py
similarity index 82%
rename from examples/python/phase-field/phasefield-static.py
rename to examples/python/phase_field_model/phasefield-static.py
index ce47516cf..f4704940f 100644
--- a/examples/python/phase-field/phasefield-static.py
+++ b/examples/python/phase_field_model/phasefield-static.py
@@ -1,125 +1,127 @@
#!/usr/bin/env python
# coding: utf-8
__copyright__ = (
"Copyright (©) 2021-2023 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")
+# Creation of the model coupler
model = aka.CouplerSolidPhaseField(mesh)
+# The model coupler contains the solid mechanics model and the phasefield model
solid = model.getSolidMechanicsModel()
phase = model.getPhaseFieldModel()
+# Each model can be initialized with the desired method
solid.initFull(_analysis_method=aka._static)
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)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
-
+# Setting the boundary conditions
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")
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()
+# Solving the problem using a staggered approach
+# The damage and displacement problems are solved until convergence for each
+# loading step
tolerance = 1e-5
steps = 1000
increment = 5e-6
for n in range(steps):
print("Computing iteration " + str(n + 1) + "/" + str(steps))
+ # Increment top displacement for mode I fracture
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:
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")
if n % 50 == 0:
solid.dump()
solid.dump()
diff --git a/examples/python/phase-field/plate.geo b/examples/python/phase_field_model/plate.geo
similarity index 100%
rename from examples/python/phase-field/plate.geo
rename to examples/python/phase_field_model/plate.geo
diff --git a/examples/python/phase-field/plate_static.geo b/examples/python/phase_field_model/plate_static.geo
similarity index 100%
rename from examples/python/phase-field/plate_static.geo
rename to examples/python/phase_field_model/plate_static.geo
diff --git a/examples/python/solid_mechanics_cohesive_model/CMakeLists.txt b/examples/python/solid_mechanics_cohesive_model/CMakeLists.txt
new file mode 100644
index 000000000..9ed940edd
--- /dev/null
+++ b/examples/python/solid_mechanics_cohesive_model/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(fragmentation)
+add_subdirectory(cohesive)
diff --git a/examples/python/solid_mechanics_cohesive_model/README.rst b/examples/python/solid_mechanics_cohesive_model/README.rst
new file mode 100644
index 000000000..6aa188b10
--- /dev/null
+++ b/examples/python/solid_mechanics_cohesive_model/README.rst
@@ -0,0 +1,6 @@
+Solid Mechanics Cohesive Model
+``````````````````````````````
+
+.. include:: examples/python/solid_mechanics_cohesive_model/cohesive/README.rst
+.. include:: examples/python/solid_mechanics_cohesive_model/fragmentation/README.rst
+
diff --git a/examples/python/cohesive/CMakeLists.txt b/examples/python/solid_mechanics_cohesive_model/cohesive/CMakeLists.txt
similarity index 100%
rename from examples/python/cohesive/CMakeLists.txt
rename to examples/python/solid_mechanics_cohesive_model/cohesive/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_cohesive_model/cohesive/README.rst b/examples/python/solid_mechanics_cohesive_model/cohesive/README.rst
new file mode 100644
index 000000000..df0e192b1
--- /dev/null
+++ b/examples/python/solid_mechanics_cohesive_model/cohesive/README.rst
@@ -0,0 +1,51 @@
+cohesive (2D)
+'''''''''''''
+
+:Sources:
+
+ .. collapse:: plate.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_cohesive_model/cohesive/plate.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_cohesive_model/cohesive/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_cohesive_model/`` `cohesive <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_cohesive_model/cohesive/>`_
+
+
+In ``cohesive/plate.py``, an example of extrinsic cohesive elements insertion is shown. This example simulates a plate
+with a pre-existing crack pulled. The geometry is depicted in :numref:`fig-ex-cohesive_plate`.
+
+.. _fig-ex-cohesive_plate:
+.. figure:: examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.svg
+ :align: center
+ :width: 25%
+
+ Problem geometry.
+
+The problem is solved statically until the onset of instability and is then solved dynamically with an explicit
+integration scheme. This is done by adding a new solver with ``model.initNewSolver()``::
+
+ model = aka.SolidMechanicsModelCohesive(mesh)
+ model.initFull(_analysis_method=aka._static, _is_extrinsic=True)
+ model.initNewSolver(aka._explicit_lumped_mass)
+ [....]
+ model.solveStep("static")
+ [....]
+ model.solveStep("explicit_lumped")
+
+The crack opening is displayed in :numref:`fig-ex-cohesive_plate_gif`.
+
+.. _fig-ex-cohesive_plate_gif:
+.. figure:: examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.gif
+ :align: center
+ :width: 50%
+
+ Stresses in the plate.
+
diff --git a/examples/python/cohesive/custom_material.py b/examples/python/solid_mechanics_cohesive_model/cohesive/custom_material.py
similarity index 100%
rename from examples/python/cohesive/custom_material.py
rename to examples/python/solid_mechanics_cohesive_model/cohesive/custom_material.py
diff --git a/examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.gif b/examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.gif
new file mode 100644
index 000000000..0b1ce3038
Binary files /dev/null and b/examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.gif differ
diff --git a/examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.svg b/examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.svg
new file mode 100644
index 000000000..8a3b6f9ea
--- /dev/null
+++ b/examples/python/solid_mechanics_cohesive_model/cohesive/images/plate.svg
@@ -0,0 +1,611 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="73.450996mm"
+ height="139.07153mm"
+ viewBox="0 0 73.450996 139.07153"
+ version="1.1"
+ id="svg9523"
+ xml:space="preserve"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview9525"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false" /><defs
+ id="defs9520"><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-6" /></marker></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-0.34275342,-0.32501118)"><g
+ id="g13435"
+ transform="translate(-10.030061,3.0709308)"><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="948.768,650.687 975.632,650.687"
+ id="polyline9666"
+ transform="matrix(0.11408815,0,0,0.11408815,-90.065042,-6.9287272)"
+ style="fill:none;stroke:#000000;stroke-width:3.76902;stroke-dasharray:none;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="948.768,113.414 948.768,650.687"
+ id="polyline9668"
+ transform="matrix(0.11408815,0,0,0.11408815,-90.065042,-6.9287272)"
+ style="fill:none;stroke:#000000;stroke-width:3.76902;stroke-dasharray:none;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1486.04,113.414 948.768,113.414"
+ id="polyline9670"
+ transform="matrix(0.11408815,0,0,0.11408815,-90.065042,-6.9287272)"
+ style="fill:none;stroke:#000000;stroke-width:3.76902;stroke-dasharray:none;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1486.04,650.687 1486.04,113.414"
+ id="polyline9672"
+ transform="matrix(0.11408815,0,0,0.11408815,-90.065042,-6.9287272)"
+ style="fill:none;stroke:#000000;stroke-width:3.76902;stroke-dasharray:none;stroke-opacity:1" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="975.632,650.687 948.768,650.687 948.768,1187.96 1486.04,1187.96 1486.04,650.687"
+ id="polyline9676"
+ transform="matrix(0.11408815,0,0,0.11408815,-90.065042,-6.9287272)"
+ style="fill:none;stroke:#000000;stroke-width:3.76902;stroke-dasharray:none;stroke-opacity:1" /><g
+ id="g4256-36-8-5-69"
+ transform="matrix(0,-0.17187009,0.20679461,0,-32.857594,154.99624)"><g
+ id="g2882-7-9-0-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-7" /></g></g><g
+ id="g4256-36-8-5-6-8"
+ transform="matrix(0,-0.17187009,0.20679461,0,-2.157594,154.96564)"><g
+ id="g2882-7-9-0-2-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-4"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-9" /></g></g><g
+ id="g4256-36-8-5-6-1-2"
+ transform="matrix(0,-0.17187009,0.20679461,0,28.542406,154.99624)"><g
+ id="g2882-7-9-0-2-8-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0-5"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8-7" /></g></g><g
+ id="g4256-36-8-7"
+ transform="matrix(0.17187009,0,0,0.20679461,-8.0940684,-45.153797)"><g
+ id="g2882-7-9-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-61"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-47" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-50" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-6" /></g></g><g
+ id="g4256-36-8-4-1"
+ transform="matrix(0.17187009,0,0,0.20679461,-8.0940684,-4.191594)"><g
+ id="g2882-7-9-7-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7-1"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7-5" /></g></g><g
+ id="g4256-36-8-5-69-8"
+ transform="matrix(0.17187009,0,0,0.20679461,-8.297806,36.772406)"><g
+ id="g2882-7-9-0-3-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-7-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-4-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-5-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-2-4"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-5-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-4-0"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-7-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-3-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-0-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-7-5" /></g></g><g
+ id="g4256-36-8-5-6-1-2-1"
+ transform="matrix(0.17187009,0,0,0.20679461,-8.0940684,77.731309)"><g
+ id="g2882-7-9-0-2-8-6-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7-6-2"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9-4-1"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2-9-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0-5-9"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2-0-9"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3-4-1"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7-8-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5-7-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9-1-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2-7-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8-7-5" /></g></g><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3)"
+ d="M 20.867153,5.1964954 V -2.07724"
+ id="path857-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5)"
+ d="M 28.834436,5.1964954 V -2.07724"
+ id="path857-7-5"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6)"
+ d="M 37.456387,5.1964954 V -2.07724"
+ id="path857-7-2"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9)"
+ d="M 45.423658,5.1964954 V -2.07724"
+ id="path857-7-5-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0)"
+ d="M 53.669897,5.3704043 V -1.9033311"
+ id="path857-7-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-3)"
+ d="M 61.637168,5.3704043 V -1.9033311"
+ id="path857-7-5-8"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-0)"
+ d="M 70.259119,5.3704043 V -1.9033311"
+ id="path857-7-2-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.399999;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-2)"
+ d="M 78.22639,5.3704043 V -1.9033311"
+ id="path857-7-5-7-9"
+ sodipodi:nodetypes="cc" /></g></g></svg>
diff --git a/examples/python/cohesive/local_material.dat b/examples/python/solid_mechanics_cohesive_model/cohesive/local_material.dat
similarity index 100%
rename from examples/python/cohesive/local_material.dat
rename to examples/python/solid_mechanics_cohesive_model/cohesive/local_material.dat
diff --git a/examples/python/cohesive/material.dat b/examples/python/solid_mechanics_cohesive_model/cohesive/material.dat
similarity index 100%
rename from examples/python/cohesive/material.dat
rename to examples/python/solid_mechanics_cohesive_model/cohesive/material.dat
diff --git a/examples/python/cohesive/plate.geo b/examples/python/solid_mechanics_cohesive_model/cohesive/plate.geo
similarity index 100%
rename from examples/python/cohesive/plate.geo
rename to examples/python/solid_mechanics_cohesive_model/cohesive/plate.geo
diff --git a/examples/python/cohesive/plate.py b/examples/python/solid_mechanics_cohesive_model/cohesive/plate.py
similarity index 100%
rename from examples/python/cohesive/plate.py
rename to examples/python/solid_mechanics_cohesive_model/cohesive/plate.py
diff --git a/examples/python/fragmentation/CMakeLists.txt b/examples/python/solid_mechanics_cohesive_model/fragmentation/CMakeLists.txt
similarity index 100%
rename from examples/python/fragmentation/CMakeLists.txt
rename to examples/python/solid_mechanics_cohesive_model/fragmentation/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_cohesive_model/fragmentation/README.rst b/examples/python/solid_mechanics_cohesive_model/fragmentation/README.rst
new file mode 100644
index 000000000..028f35d70
--- /dev/null
+++ b/examples/python/solid_mechanics_cohesive_model/fragmentation/README.rst
@@ -0,0 +1,33 @@
+fragmentation (2D)
+''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: fragmentation.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_cohesive_model/fragmentation/fragmentation.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_cohesive_model/fragmentation/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_cohesive_model/`` `fragmentation <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_cohesive_model/fragmentation/>`_
+
+
+``fragmentation`` shows an example of a 1D bar fragmentation with extrinsic cohesive elements. It uses a custom boundary
+condition to impose a constant velocity. This is done by creating a class that inherits from ``DirichletFunctor``.
+The result is shown in :numref:`fig-ex-fragmentation`.
+
+.. _fig-ex-fragmentation:
+.. figure:: examples/python/solid_mechanics_cohesive_model/fragmentation/images/fragmentation.gif
+ :align: center
+ :width: 100%
+
+ 1D bar fragmentation.
+
+
diff --git a/examples/python/fragmentation/fragmentation.py b/examples/python/solid_mechanics_cohesive_model/fragmentation/fragmentation.py
similarity index 100%
rename from examples/python/fragmentation/fragmentation.py
rename to examples/python/solid_mechanics_cohesive_model/fragmentation/fragmentation.py
diff --git a/examples/python/fragmentation/fragmentation_mesh.geo b/examples/python/solid_mechanics_cohesive_model/fragmentation/fragmentation_mesh.geo
similarity index 100%
rename from examples/python/fragmentation/fragmentation_mesh.geo
rename to examples/python/solid_mechanics_cohesive_model/fragmentation/fragmentation_mesh.geo
diff --git a/examples/python/solid_mechanics_cohesive_model/fragmentation/images/fragmentation.gif b/examples/python/solid_mechanics_cohesive_model/fragmentation/images/fragmentation.gif
new file mode 100644
index 000000000..7a98a9762
Binary files /dev/null and b/examples/python/solid_mechanics_cohesive_model/fragmentation/images/fragmentation.gif differ
diff --git a/examples/python/fragmentation/material.dat b/examples/python/solid_mechanics_cohesive_model/fragmentation/material.dat
similarity index 100%
rename from examples/python/fragmentation/material.dat
rename to examples/python/solid_mechanics_cohesive_model/fragmentation/material.dat
diff --git a/examples/python/solid_mechanics_model/CMakeLists.txt b/examples/python/solid_mechanics_model/CMakeLists.txt
new file mode 100644
index 000000000..09e39cbac
--- /dev/null
+++ b/examples/python/solid_mechanics_model/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_subdirectory(custom-material)
+add_subdirectory(dynamics)
+add_subdirectory(eigen_modes)
+add_subdirectory(plate-hole)
+add_subdirectory(stiffness_matrix)
+add_subdirectory(solver_callback)
diff --git a/examples/python/solid_mechanics_model/README.rst b/examples/python/solid_mechanics_model/README.rst
new file mode 100644
index 000000000..02e3e67d8
--- /dev/null
+++ b/examples/python/solid_mechanics_model/README.rst
@@ -0,0 +1,20 @@
+Solid Mechanics Model
+`````````````````````
+
+The Solid Mechanics Model is initialized with:
+
+.. code-block:: python
+
+ model = aka.SolidMechanicsModel(mesh)
+
+.. include:: examples/python/solid_mechanics_model/plate-hole/README.rst
+
+.. include:: examples/python/solid_mechanics_model/dynamics/README.rst
+
+.. include:: examples/python/solid_mechanics_model/eigen_modes/README.rst
+
+.. include:: examples/python/solid_mechanics_model/custom-material/README.rst
+
+.. include:: examples/python/solid_mechanics_model/stiffness_matrix/README.rst
+
+.. include:: examples/python/solid_mechanics_model/solver_callback/README.rst
diff --git a/examples/python/custom-material/CMakeLists.txt b/examples/python/solid_mechanics_model/custom-material/CMakeLists.txt
similarity index 100%
rename from examples/python/custom-material/CMakeLists.txt
rename to examples/python/solid_mechanics_model/custom-material/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_model/custom-material/README.rst b/examples/python/solid_mechanics_model/custom-material/README.rst
new file mode 100644
index 000000000..e52040bd6
--- /dev/null
+++ b/examples/python/solid_mechanics_model/custom-material/README.rst
@@ -0,0 +1,59 @@
+custom-material (2D)
+''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: custom-material.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/custom-material/custom-material.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: bi-material.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/custom-material/bi-material.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/plate-hole/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_model/`` `custom-material <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_model/custom-material/>`_
+
+In ``custom-material.py`` it is shown how to create a custom material behaviour. In this example, a linear elastic
+material is recreated. It is done by creating a class that inherits from ``aka.Material`` (``LocalElastic(aka.Material)`` in this case) and register it
+to ``MaterialFactory``::
+
+ class LocalElastic(aka.Material):
+ [...]
+
+ def allocator(_dim, unused, model, _id):
+ return LocalElastic(model, _id)
+
+ mat_factory = aka.MaterialFactory.getInstance()
+ mat_factory.registerAllocator("local_elastic", allocator)
+
+Wave propagation of a pulse in a bar fixed on the top, bottom and right boundaries is simulated using an explicit
+scheme. Results are shown in :numref:`fig-ex-plate_bar_custom`.
+
+.. _fig-ex-plate_bar_custom:
+.. figure:: examples/python/solid_mechanics_model/custom-material/images/pulse_bar_custom.gif
+ :align: center
+ :width: 90%
+
+ Wave propagation in a bar.
+
+In ``bi-material.py``, the same principle is used to create a bimaterial square. The displacement is shown in :numref:`fig-ex-square_custom`.
+
+.. _fig-ex-square_custom:
+.. figure:: examples/python/solid_mechanics_model/custom-material/images/square_displ.png
+ :align: center
+ :width: 60%
+
+ Bimaterial square.
+
+
diff --git a/examples/python/custom-material/bar.geo b/examples/python/solid_mechanics_model/custom-material/bar.geo
similarity index 100%
rename from examples/python/custom-material/bar.geo
rename to examples/python/solid_mechanics_model/custom-material/bar.geo
diff --git a/examples/python/custom-material/bi-material.py b/examples/python/solid_mechanics_model/custom-material/bi-material.py
similarity index 88%
rename from examples/python/custom-material/bi-material.py
rename to examples/python/solid_mechanics_model/custom-material/bi-material.py
index f53957398..6d95b8870 100644
--- a/examples/python/custom-material/bi-material.py
+++ b/examples/python/solid_mechanics_model/custom-material/bi-material.py
@@ -1,187 +1,185 @@
__copyright__ = (
"Copyright (©) 2018-2023 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
# ------------------------------------------------------------------------------
class LocalElastic(aka.Material):
def __init__(self, model, _id):
super().__init__(model, _id)
super().registerParamReal('E',
aka._pat_readable | aka._pat_parsable,
'Youngs modulus')
super().registerParamReal('nu',
aka._pat_readable | aka._pat_parsable,
'Poisson ratio')
# change it to have the initialize wrapped
- super().registerInternalReal('factor', 1)
- super().registerInternalReal('quad_coordinates', 2)
+ self.factor = super().registerInternalReal('factor', 1)
+ self.quad_coords = super().registerInternalReal('quad_coordinates', 2)
def initMaterial(self):
nu = self.getReal('nu')
E = self.getReal('E')
self.mu = E / (2 * (1 + nu))
self.lame_lambda = nu * E / (
(1. + nu) * (1. - 2. * nu))
# Second Lame coefficient (shear modulus)
self.lame_mu = E / (2. * (1. + nu))
super().initMaterial()
- quad_coords = self.getInternalReal("quad_coordinates")
- factor = self.getInternalReal("factor")
model = self.getModel()
model.getFEEngine().computeIntegrationPointsCoordinates(
- quad_coords, self.getElementFilter())
+ self.quad_coords, self.getElementFilter())
- for elem_type in factor.elementTypes():
- factor = factor(elem_type)
- coords = quad_coords(elem_type)
+ for elem_type in self.factor.elementTypes():
+ factor = self.factor(elem_type)
+ coords = self.quad_coords(elem_type)
factor[:] = 1.
factor[coords[:, 1] < 0.5] = .5
# declares all the parameters that are needed
def getPushWaveSpeed(self, params):
return np.sqrt((self.lame_lambda + 2 * self.lame_mu) / self.rho)
# compute small deformation tensor
@staticmethod
def computeEpsilon(grad_u):
return 0.5 * (grad_u + np.einsum('aij->aji', grad_u))
# constitutive law
def computeStress(self, el_type, ghost_type):
grad_u = self.getGradU(el_type, ghost_type)
sigma = self.getStress(el_type, ghost_type)
n_quads = grad_u.shape[0]
grad_u = grad_u.reshape((n_quads, 2, 2))
factor = self.getInternalReal('factor')(
el_type, ghost_type).reshape(n_quads)
epsilon = self.computeEpsilon(grad_u)
sigma = sigma.reshape((n_quads, 2, 2))
trace = np.einsum('aii->a', grad_u)
sigma[:, :, :] = (
np.einsum('a,ij->aij', trace,
self.lame_lambda * np.eye(2))
+ 2. * self.lame_mu * epsilon)
sigma[:, :, :] = np.einsum('aij, a->aij', sigma, factor)
# constitutive law tangent modulii
def computeTangentModuli(self, el_type, tangent_matrix, ghost_type):
n_quads = tangent_matrix.shape[0]
tangent = tangent_matrix.reshape(n_quads, 3, 3)
factor = self.getInternalReal('factor')(
el_type, ghost_type).reshape(n_quads)
Miiii = self.lame_lambda + 2 * self.lame_mu
Miijj = self.lame_lambda
Mijij = self.lame_mu
tangent[:, 0, 0] = Miiii
tangent[:, 1, 1] = Miiii
tangent[:, 0, 1] = Miijj
tangent[:, 1, 0] = Miijj
tangent[:, 2, 2] = Mijij
tangent[:, :, :] = np.einsum('aij, a->aij', tangent, factor)
# computes the energy density
def computePotentialEnergy(self, el_type):
sigma = self.getStress(el_type)
grad_u = self.getGradU(el_type)
nquads = sigma.shape[0]
stress = sigma.reshape(nquads, 2, 2)
grad_u = grad_u.reshape((nquads, 2, 2))
epsilon = self.computeEpsilon(grad_u)
energy_density = self.getPotentialEnergy(el_type)
energy_density[:, 0] = 0.5 * np.einsum('aij,aij->a', stress, epsilon)
# ------------------------------------------------------------------------------
# applies manually the boundary conditions
def applyBC(model):
nbNodes = model.getMesh().getNbNodes()
position = model.getMesh().getNodes()
displacement = model.getDisplacement()
blocked_dofs = model.getBlockedDOFs()
width = 1.
height = 1.
epsilon = 1e-8
for node in range(0, nbNodes):
- if((np.abs(position[node, 0]) < epsilon) or # left side
- (np.abs(position[node, 0] - width) < epsilon)): # right side
+ if ((np.abs(position[node, 0]) < epsilon) or
+ (np.abs(position[node, 0] - width) < epsilon)):
blocked_dofs[node, 0] = True
displacement[node, 0] = 0 * position[node, 0] + 0.
- if(np.abs(position[node, 1]) < epsilon): # lower side
+ if np.abs(position[node, 1]) < epsilon: # lower side
blocked_dofs[node, 1] = True
displacement[node, 1] = - 1.
- if(np.abs(position[node, 1] - height) < epsilon): # upper side
+ if np.abs(position[node, 1] - height) < epsilon: # upper side
blocked_dofs[node, 1] = True
displacement[node, 1] = 1.
# register the material to the material factory
def allocator(dim, option, model, id):
return LocalElastic(model, id)
mat_factory = aka.MaterialFactory.getInstance()
mat_factory.registerAllocator("local_elastic", allocator)
# main parameters
spatial_dimension = 2
mesh_file = 'square.msh'
# read mesh
mesh = aka.Mesh(spatial_dimension)
mesh.read(mesh_file)
# parse input file
aka.parseInput('material.dat')
# init the SolidMechanicsModel
model = aka.SolidMechanicsModel(mesh)
model.initFull(_analysis_method=aka._static)
# configure the solver
solver = model.getNonLinearSolver()
solver.set("max_iterations", 2)
solver.set("threshold", 1e-3)
solver.set("convergence_type", aka.SolveConvergenceCriteria.solution)
# prepare the dumper
model.setBaseName("bimaterial")
model.addDumpFieldVector("displacement")
model.addDumpFieldVector("internal_force")
model.addDumpFieldVector("external_force")
model.addDumpField("strain")
model.addDumpField("stress")
-# model.addDumpField("factor")
+model.addDumpField("factor")
model.addDumpField("blocked_dofs")
# Boundary conditions
applyBC(model)
# solve the problem
model.solveStep()
# dump paraview files
model.dump()
epot = model.getEnergy('potential')
print('Potential energy: ' + str(epot))
diff --git a/examples/python/custom-material/custom-material.py b/examples/python/solid_mechanics_model/custom-material/custom-material.py
similarity index 100%
rename from examples/python/custom-material/custom-material.py
rename to examples/python/solid_mechanics_model/custom-material/custom-material.py
diff --git a/examples/python/solid_mechanics_model/custom-material/images/pulse_bar_custom.gif b/examples/python/solid_mechanics_model/custom-material/images/pulse_bar_custom.gif
new file mode 100644
index 000000000..6c4e61a5d
Binary files /dev/null and b/examples/python/solid_mechanics_model/custom-material/images/pulse_bar_custom.gif differ
diff --git a/examples/python/solid_mechanics_model/custom-material/images/square_displ.png b/examples/python/solid_mechanics_model/custom-material/images/square_displ.png
new file mode 100644
index 000000000..65916137b
Binary files /dev/null and b/examples/python/solid_mechanics_model/custom-material/images/square_displ.png differ
diff --git a/examples/python/custom-material/material.dat b/examples/python/solid_mechanics_model/custom-material/material.dat
similarity index 100%
rename from examples/python/custom-material/material.dat
rename to examples/python/solid_mechanics_model/custom-material/material.dat
diff --git a/examples/python/custom-material/square.geo b/examples/python/solid_mechanics_model/custom-material/square.geo
similarity index 100%
rename from examples/python/custom-material/square.geo
rename to examples/python/solid_mechanics_model/custom-material/square.geo
diff --git a/examples/python/dynamics/CMakeLists.txt b/examples/python/solid_mechanics_model/dynamics/CMakeLists.txt
similarity index 100%
rename from examples/python/dynamics/CMakeLists.txt
rename to examples/python/solid_mechanics_model/dynamics/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_model/dynamics/README.rst b/examples/python/solid_mechanics_model/dynamics/README.rst
new file mode 100644
index 000000000..c4e82df87
--- /dev/null
+++ b/examples/python/solid_mechanics_model/dynamics/README.rst
@@ -0,0 +1,52 @@
+dynamics (2D)
+'''''''''''''
+
+:Sources:
+
+ .. collapse:: dynamics.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/dynamics/dynamics.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/dynamics/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_model/`` `dynamics <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_model/dynamics/>`_
+
+In ``dynamics``, an example of a dynamic simulation solved with an explicit time intergration is shown. This examples
+model the propagation of a wave in a bar. The geometry is depicted in :numref:`fig-ex-dynamics_geom`. A pulse is impose
+as an initial displacement over the bar. Results are depicted in :numref:`fig-ex-dynamics_displ`.
+
+The explicit time integration scheme is set with:
+
+.. code-block:: python
+
+ model.initFull(_analysis_method=aka._explicit_lumped_mass)
+
+This example shows how to create a new functor to set the boundary conditions. This is done by creating a class that inherits from ``aka.FixedValue`` (``MyFixedValue(aka.FixedValue)`` in this case).
+The boundary conditions are then applied with:
+
+.. code-block:: python
+
+ model.applyBC(MyFixedValue(0, aka._x), "XBlocked")
+ model.applyBC(MyFixedValue(0, aka._y), "YBlocked")
+
+.. _fig-ex-dynamics_geom:
+.. figure:: examples/python/solid_mechanics_model/dynamics/images/bar_geom.svg
+ :align: center
+ :width: 70%
+
+ Plate with a hole geometry.
+
+.. _fig-ex-dynamics_displ:
+.. figure:: examples/python/solid_mechanics_model/dynamics/images/bar.gif
+ :align: center
+ :width: 70%
+
+ Displacement magnitude.
+
diff --git a/examples/python/dynamics/bar.geo b/examples/python/solid_mechanics_model/dynamics/bar.geo
similarity index 100%
rename from examples/python/dynamics/bar.geo
rename to examples/python/solid_mechanics_model/dynamics/bar.geo
diff --git a/examples/python/dynamics/dynamics.py b/examples/python/solid_mechanics_model/dynamics/dynamics.py
similarity index 100%
rename from examples/python/dynamics/dynamics.py
rename to examples/python/solid_mechanics_model/dynamics/dynamics.py
diff --git a/examples/python/solid_mechanics_model/dynamics/images/bar.gif b/examples/python/solid_mechanics_model/dynamics/images/bar.gif
new file mode 100644
index 000000000..e42ad7c69
Binary files /dev/null and b/examples/python/solid_mechanics_model/dynamics/images/bar.gif differ
diff --git a/examples/python/solid_mechanics_model/dynamics/images/bar_geom.svg b/examples/python/solid_mechanics_model/dynamics/images/bar_geom.svg
new file mode 100644
index 000000000..5fdb3d992
--- /dev/null
+++ b/examples/python/solid_mechanics_model/dynamics/images/bar_geom.svg
@@ -0,0 +1,729 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="157.08885mm"
+ height="25.914673mm"
+ viewBox="0 0 157.08885 25.914673"
+ version="1.1"
+ id="svg1574"
+ xml:space="preserve"
+ inkscape:export-filename="bar_geom.svg"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview1576"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false" /><defs
+ id="defs1571"><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0.03581354,-0.09025789)"><ellipse
+ fill="#5a5a5a"
+ cx="4.2489347"
+ cy="18.684511"
+ id="circle1701"
+ rx="0.17213884"
+ ry="0.13083322"
+ style="stroke-width:0.0750358" /><ellipse
+ fill="#5a5a5a"
+ cx="149.33762"
+ cy="18.684511"
+ id="circle1703"
+ rx="0.17213884"
+ ry="0.13083322"
+ style="stroke-width:0.0750358" /><ellipse
+ fill="#5a5a5a"
+ cx="149.33762"
+ cy="13.170805"
+ id="circle1705"
+ rx="0.17213884"
+ ry="0.13083322"
+ style="stroke-width:0.0750358" /><ellipse
+ fill="#5a5a5a"
+ cx="149.33762"
+ cy="7.6571007"
+ id="circle1707"
+ rx="0.17213884"
+ ry="0.13083322"
+ style="stroke-width:0.0750358" /><ellipse
+ fill="#5a5a5a"
+ cx="4.2489347"
+ cy="7.6571007"
+ id="circle1709"
+ rx="0.17213884"
+ ry="0.13083322"
+ style="stroke-width:0.0750358" /><ellipse
+ fill="#5a5a5a"
+ cx="4.2489347"
+ cy="13.170805"
+ id="circle1711"
+ rx="0.17213884"
+ ry="0.13083322"
+ style="stroke-width:0.0750358" /><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="337.143,740.786 2022.86,740.786 2022.86,656.5 2022.86,572.214 337.143,572.214 337.143,656.5 337.143,740.786"
+ id="polyline1713"
+ transform="matrix(0.08606942,0,0,0.06541661,-24.768768,-29.775198)"
+ style="fill:#b3b3b3;stroke:#000000;stroke-width:5.99714;stroke-dasharray:none" /><g
+ id="g4256"
+ transform="matrix(-0.17201065,0,0,-0.1969014,175.73895,61.772712)"><g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" /></g></g><g
+ id="g9336-9"
+ transform="matrix(-1.0502445,0,0,-0.99918287,171.3187,86.741385)"><g
+ id="g4256-36-8-7"
+ transform="matrix(0,-0.17201065,0.1969014,0,-27.647856,105.40788)"><g
+ id="g2882-7-9-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-61"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-47" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-50" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-6" /></g></g><g
+ id="g4256-36-8-4-1"
+ transform="matrix(0,-0.17201065,0.1969014,0,6.894128,105.40788)"><g
+ id="g2882-7-9-7-0"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6-2"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7-1"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7-5" /></g></g><g
+ id="g4256-36-8-5-69"
+ transform="matrix(0,-0.17201065,0.1969014,0,41.436112,105.40788)"><g
+ id="g2882-7-9-0-3"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-7"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-7" /></g></g><g
+ id="g4256-36-8-5-6-8"
+ transform="matrix(0,-0.17201065,0.1969014,0,75.978096,105.40788)"><g
+ id="g2882-7-9-0-2-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-4"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-9" /></g></g><g
+ id="g4256-36-8-5-6-1-2"
+ transform="matrix(0,-0.17201065,0.1969014,0,110.52008,105.40788)"><g
+ id="g2882-7-9-0-2-8-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0-5"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3-4"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8-7" /></g></g></g><g
+ id="g9336-9-6"
+ transform="matrix(1.0502445,0,0,0.99918287,-17.708401,-60.646197)"><g
+ id="g4256-36-8-7-7"
+ transform="matrix(0,-0.17201065,0.1969014,0,-27.647856,105.40788)"><g
+ id="g2882-7-9-3-5"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-61-3"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-2-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-9-6"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-3-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-1-9"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-9-1"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-47-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-8-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-4-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-50-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-3-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-6-6" /></g></g><g
+ id="g4256-36-8-4-1-0"
+ transform="matrix(0,-0.17201065,0.1969014,0,6.894128,105.40788)"><g
+ id="g2882-7-9-7-0-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-6-6-2"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-5-3-6"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-6-2-1"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-9-0-8"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-3-6-7"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-7-1-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-4-5-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-5-5-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-2-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-5-7-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-4-6-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-7-5-5" /></g></g><g
+ id="g4256-36-8-5-69-9"
+ transform="matrix(0,-0.17201065,0.1969014,0,41.436112,105.40788)"><g
+ id="g2882-7-9-0-3-2"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-7-2"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-4-8"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-5-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-2-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-5-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-4-6"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-7-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-4-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-4-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-3-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-0-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-7-9" /></g></g><g
+ id="g4256-36-8-5-6-8-4"
+ transform="matrix(0,-0.17201065,0.1969014,0,75.978096,105.40788)"><g
+ id="g2882-7-9-0-2-6-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-8-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-8-4"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-4-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-3-0"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-1-3"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-4-6"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-9-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-2-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-0-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-6-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-8-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-9-0" /></g></g><g
+ id="g4256-36-8-5-6-1-2-6"
+ transform="matrix(0,-0.17201065,0.1969014,0,110.52008,105.40788)"><g
+ id="g2882-7-9-0-2-8-6-1"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-7-3-9-7-6-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-3-6-1-9-4-5"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-6-1-2-2-9-4"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-1-0-7-0-5-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-2-6-0-2-0-6"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-9-3-9-3-4-5"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-31-2-3-7-8-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-9-0-6-5-7-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-4-6-0-9-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-7-1-6-2-7-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-8-5-2-2-2-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-4-5-6-8-7-5" /></g></g></g></g></svg>
diff --git a/examples/python/dynamics/material.dat b/examples/python/solid_mechanics_model/dynamics/material.dat
similarity index 100%
rename from examples/python/dynamics/material.dat
rename to examples/python/solid_mechanics_model/dynamics/material.dat
diff --git a/examples/python/eigen_modes/CMakeLists.txt b/examples/python/solid_mechanics_model/eigen_modes/CMakeLists.txt
similarity index 100%
rename from examples/python/eigen_modes/CMakeLists.txt
rename to examples/python/solid_mechanics_model/eigen_modes/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_model/eigen_modes/README.rst b/examples/python/solid_mechanics_model/eigen_modes/README.rst
new file mode 100644
index 000000000..aa5f33109
--- /dev/null
+++ b/examples/python/solid_mechanics_model/eigen_modes/README.rst
@@ -0,0 +1,36 @@
+eigen_modes (2D)
+''''''''''''''''
+
+:Sources:
+
+ .. collapse:: eigen_modes.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/eigen_modes/eigen_modes.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/eigen_modes/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_model/`` `eigen_modes <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_model/eigen_modes/>`_
+
+
+In ``eigen_modes`` it is shown how to compute the eigen modes using the library `scipy.sparse`. The mode can be specify with the ``-m`` argument. Simulation is performed on a bar where a pulse is imposed.
+The ``-p`` argument will plot the following figures :numref:`fig-ex-eigen`:
+
+.. _fig-ex-eigen:
+.. figure:: examples/python/solid_mechanics_model/eigen_modes/images/eigen_modes.png
+ :align: center
+ :width: 80%
+
+ Energy norms as a fonction of time (left), space-time diagram for diplacements (center) and space-time
+ diagram for velocities (right) with the default values.
+
+An implicit time integration scheme is used and set with::
+ model.initFull(aka._implicit_dynamic)
+
+
diff --git a/examples/python/eigen_modes/eigen_modes.py b/examples/python/solid_mechanics_model/eigen_modes/eigen_modes.py
similarity index 100%
rename from examples/python/eigen_modes/eigen_modes.py
rename to examples/python/solid_mechanics_model/eigen_modes/eigen_modes.py
diff --git a/examples/python/eigen_modes/image_saver.py b/examples/python/solid_mechanics_model/eigen_modes/image_saver.py
similarity index 100%
rename from examples/python/eigen_modes/image_saver.py
rename to examples/python/solid_mechanics_model/eigen_modes/image_saver.py
diff --git a/examples/python/solid_mechanics_model/eigen_modes/images/eigen_modes.png b/examples/python/solid_mechanics_model/eigen_modes/images/eigen_modes.png
new file mode 100644
index 000000000..27b357d8c
Binary files /dev/null and b/examples/python/solid_mechanics_model/eigen_modes/images/eigen_modes.png differ
diff --git a/examples/python/eigen_modes/material.dat b/examples/python/solid_mechanics_model/eigen_modes/material.dat
similarity index 100%
rename from examples/python/eigen_modes/material.dat
rename to examples/python/solid_mechanics_model/eigen_modes/material.dat
diff --git a/examples/python/plate-hole/CMakeLists.txt b/examples/python/solid_mechanics_model/plate-hole/CMakeLists.txt
similarity index 100%
rename from examples/python/plate-hole/CMakeLists.txt
rename to examples/python/solid_mechanics_model/plate-hole/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_model/plate-hole/README.rst b/examples/python/solid_mechanics_model/plate-hole/README.rst
new file mode 100644
index 000000000..a38389ca5
--- /dev/null
+++ b/examples/python/solid_mechanics_model/plate-hole/README.rst
@@ -0,0 +1,68 @@
+plate_hole (2D)
+'''''''''''''''
+
+:Sources:
+
+ .. collapse:: plate.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/plate-hole/plate.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/plate-hole/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_model/`` `plate-hole <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_model/plate-hole/>`_
+
+In ``plate_hole``, an example of a static solution of a loaded plate with a hole. Because of the symmetries, only a quarter of the problem is modeled. The corresponding domain and boundary conditions is shown in :numref:`fig-ex-plate_hole`.
+The static solver is initialized with:
+
+.. code-block:: python
+
+ model.initFull(_analysis_method=aka._static)
+
+Boundary conditions are applied with:
+
+.. code-block:: python
+
+ model.applyBC(aka.FixedValue(0.0, aka._x), "XBlocked")
+ model.applyBC(aka.FixedValue(0.0, aka._y), "YBlocked")
+ model.applyBC(aka.FromTraction(trac), "Traction")
+
+where ``trac`` is a numpy array of size ``spatial_dimension``.
+
+Additionally, the simulation can be run in parallel. To do so, the following lines are added:
+
+.. code-block:: python
+
+ try:
+ from mpi4py import MPI
+ comm = MPI.COMM_WORLD
+ prank = comm.Get_rank()
+ except ImportError:
+ prank = 0
+
+Similarly to C++, the mesh has to be distributed between the processors with::
+
+ mesh.distribute()
+
+.. _fig-ex-plate_hole:
+.. figure:: examples/python/solid_mechanics_model/plate-hole/images/plate_hole.svg
+ :align: center
+ :width: 30%
+
+ Plate with a hole geometry.
+
+The displacement magnitude is displayed in :numref:`fig-ex-plate_hole_displ`.
+
+.. _fig-ex-plate_hole_displ:
+.. figure:: examples/python/solid_mechanics_model/plate-hole/images/plate_hole_displ_mag.png
+ :align: center
+ :width: 40%
+
+ Displacement magnitude.
+
diff --git a/examples/python/solid_mechanics_model/plate-hole/images/plate_hole.svg b/examples/python/solid_mechanics_model/plate-hole/images/plate_hole.svg
new file mode 100644
index 000000000..0a66fbd25
--- /dev/null
+++ b/examples/python/solid_mechanics_model/plate-hole/images/plate_hole.svg
@@ -0,0 +1,618 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="119mm"
+ height="124mm"
+ viewBox="0 0 119 123.99999"
+ version="1.1"
+ id="svg5"
+ xml:space="preserve"
+ inkscape:export-filename="plate_hole.svg"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
+ id="namedview7"
+ pagecolor="#505050"
+ bordercolor="#eeeeee"
+ borderopacity="1"
+ inkscape:showpageshadow="0"
+ inkscape:pageopacity="0"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#505050"
+ inkscape:document-units="mm"
+ showgrid="false" /><defs
+ id="defs2"><linearGradient
+ id="linearGradient7134"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#000000;stop-opacity:1;"
+ offset="0"
+ id="stop7132" /></linearGradient><linearGradient
+ id="linearGradient4824"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ffffff;stop-opacity:1;"
+ offset="0"
+ id="stop4822" /></linearGradient><linearGradient
+ id="linearGradient4804"
+ inkscape:swatch="solid"><stop
+ style="stop-color:#ff0002;stop-opacity:1;"
+ offset="0"
+ id="stop4802" /></linearGradient><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"
+ inkscape:collect="always"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-3"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-0"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-6" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-0" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-3" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-6-7"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-2-5" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-5-9-9"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-3-1-2" /></marker><marker
+ style="overflow:visible"
+ id="Arrow2Lend-3-0-2"
+ refX="0"
+ refY="0"
+ orient="auto"
+ inkscape:stockid="Arrow2Lend"
+ inkscape:isstock="true"><path
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:0.625;stroke-linejoin:round;stroke-opacity:1"
+ id="path880-6-9-8" /></marker></defs><g
+ inkscape:label="Calque 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(108.86825,118.18664)"><circle
+ fill="#5a5a5a"
+ cx="-108.1627"
+ cy="-117.48109"
+ r="0.70555556"
+ id="circle258"
+ style="stroke-width:0.352778" /><g
+ id="g11407"
+ transform="translate(-145.8863,-134.98827)"
+ inkscape:export-filename="./g11407.svg"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96"><polyline
+ fill="none"
+ stroke="#0000ff"
+ stroke-width="2"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="670.554,858.045 670.516,854.232 670.404,850.421 670.217,846.613 669.955,842.81 669.619,839.012 669.208,835.221 668.722,831.44 668.163,827.668 667.53,823.908 666.823,820.162 666.042,816.43 665.188,812.714 664.262,809.016 663.263,805.336 662.192,801.677 661.05,798.039 659.836,794.425 658.552,790.835 657.197,787.271 655.773,783.735 654.279,780.227 652.717,776.749 651.087,773.302 649.389,769.888 647.625,766.508 645.795,763.163 643.899,759.855 641.939,756.585 639.915,753.354 637.828,750.163 635.679,747.014 633.468,743.908 631.197,740.845 628.866,737.828 626.476,734.857 624.029,731.934 621.524,729.059 618.964,726.234 616.349,723.46 613.679,720.737 610.957,718.068 608.183,715.453 605.358,712.892 602.483,710.388 599.559,707.94 596.589,705.55 593.571,703.22 590.509,700.948 587.403,698.738 584.253,696.588 581.063,694.501 577.832,692.477 574.561,690.517 571.253,688.622 567.909,686.792 564.529,685.027 561.115,683.33 557.668,681.7 554.19,680.138 550.682,678.644 547.145,677.22 543.581,675.865 539.992,674.581 536.377,673.367 532.74,672.224 529.081,671.153 525.401,670.155 521.703,669.228 517.987,668.375 514.255,667.594 510.508,666.887 506.748,666.254 502.977,665.694 499.195,665.209 495.405,664.798 491.607,664.461 487.803,664.2 483.995,664.013 480.184,663.9 476.372,663.863 476.372,81.3167 1253.1,81.3167 1253.1,858.045 670.554,858.045"
+ id="polyline264"
+ transform="matrix(0.1327162,0,0,0.1327162,-15.540418,15.606149)"
+ style="fill:none;stroke:#000000;stroke-width:5.76418;stroke-dasharray:none;stroke-opacity:1" /><g
+ id="g4256"
+ transform="matrix(0.22990137,0,0,0.26316918,12.47101,-38.428756)"><g
+ id="g2882"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97" /></g></g><g
+ id="g4256-36"
+ transform="matrix(0.22990137,0,0,0.26316918,12.721162,38.629648)"><g
+ id="g2882-7"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62" /></g></g><g
+ id="g4256-36-6"
+ transform="matrix(0.22990137,0,0,0.26316918,12.561809,-0.05095426)"><g
+ id="g2882-7-1"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-8"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-7"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-2"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-0"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-2"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-2" /></g></g><g
+ id="g3998"
+ transform="rotate(-90,65.171964,125.27446)"><g
+ id="g4256-3"
+ transform="matrix(0.22990137,0,0,0.26316918,25.5519,68.973887)"><g
+ id="g2882-5"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-6"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-1"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-27"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-0"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-3" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-0" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-6" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-2" /></g></g><g
+ id="g4256-36-61"
+ transform="matrix(0.22990137,0,0,0.26316918,25.802052,146.03212)"><g
+ id="g2882-7-8"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-79"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-0"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-23"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-7"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-5"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-2" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-9" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-7" /></g></g><g
+ id="g4256-36-6-3"
+ transform="matrix(0.22990137,0,0,0.26316918,25.642699,107.35152)"><g
+ id="g2882-7-1-6"
+ transform="translate(-58.667089,88.9002)"><path
+ sodipodi:type="star"
+ style="fill:none;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path510-5-8-1"
+ inkscape:flatsided="false"
+ sodipodi:sides="3"
+ sodipodi:cx="153.02002"
+ sodipodi:cy="64.125938"
+ sodipodi:r1="17.89472"
+ sodipodi:r2="8.94736"
+ sodipodi:arg1="0"
+ sodipodi:arg2="1.0471976"
+ inkscape:rounded="0"
+ inkscape:randomized="0"
+ d="M 170.91474,64.125938 157.4937,71.87458 144.07266,79.623221 V 64.125938 48.628656 l 13.42104,7.748642 z"
+ inkscape:transform-center-x="-4.4736798"
+ transform="translate(37.745764,93.689667)" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-3-7-2"
+ cx="210.67387"
+ cy="157.8156"
+ r="3.0005257" /><g
+ id="g2875-5-9-9"
+ transform="translate(7.5,-0.54516576)"><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-6-2-3"
+ cx="170.69357"
+ cy="168.30325"
+ r="3.0005257" /><circle
+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2.1;stroke-dasharray:none;stroke-opacity:1"
+ id="path1347-7-5-2-0-1"
+ cx="170.69357"
+ cy="148.41829"
+ r="3.0005257" /></g></g><g
+ id="g4241-9-2-9"
+ transform="translate(18,-7.5)"><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 98.331801,234.43859 -0.355215,40.37778"
+ id="path3427-1-3-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,235.0117 5.089095,6.38696"
+ id="path3429-27-7-7" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,242.47285 5.089095,6.38696"
+ id="path3429-9-09-5-8" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,249.934 5.089095,6.38696"
+ id="path3429-2-36-9-4" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037424,257.39515 5.089094,6.38696"
+ id="path3429-28-0-2-5" /><path
+ style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
+ d="m 92.037423,264.8563 5.089095,6.38696"
+ id="path3429-97-62-2-0" /></g></g></g><polyline
+ fill="none"
+ stroke="#000000"
+ stroke-width="1"
+ stroke-linecap="butt"
+ stroke-linejoin="miter"
+ points="1660,921 1660,921"
+ id="polyline216"
+ transform="matrix(0,-0.11827043,0.11827043,0,33.573406,337.15564)" /><g
+ id="g7708"
+ transform="matrix(1.8103994,0,0,0.9498032,-64.432142,-128.13932)"
+ style="stroke-width:0.305039;stroke-dasharray:none"><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3)"
+ d="m 62.833025,161.28886 v -7.65815"
+ id="path857-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5)"
+ d="m 67.233868,161.28886 v -7.65815"
+ id="path857-7-5"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6)"
+ d="m 71.996326,161.28886 v -7.65815"
+ id="path857-7-2"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9)"
+ d="m 76.397162,161.28886 v -7.65815"
+ id="path857-7-5-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0)"
+ d="m 80.95209,161.47196 v -7.65815"
+ id="path857-7-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-3)"
+ d="m 85.352926,161.47196 v -7.65815"
+ id="path857-7-5-8"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-0)"
+ d="m 90.115384,161.47196 v -7.65815"
+ id="path857-7-2-7"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-2)"
+ d="m 94.51622,161.47196 v -7.65815"
+ id="path857-7-5-7-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-2)"
+ d="m 99.582487,161.53808 v -7.65815"
+ id="path857-7-9"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-2)"
+ d="m 103.98332,161.53808 v -7.65815"
+ id="path857-7-5-3"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-6-7)"
+ d="m 108.74577,161.53808 v -7.65815"
+ id="path857-7-2-1"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-5-9-9)"
+ d="m 113.14662,161.53808 v -7.65815"
+ id="path857-7-5-7-94"
+ sodipodi:nodetypes="cc" /><path
+ style="fill:none;stroke:#000000;stroke-width:0.305039;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow2Lend-3-0-2)"
+ d="m 117.70154,161.72118 v -7.65815"
+ id="path857-7-1-7"
+ sodipodi:nodetypes="cc" /></g></g></g></svg>
diff --git a/examples/python/solid_mechanics_model/plate-hole/images/plate_hole_displ_mag.png b/examples/python/solid_mechanics_model/plate-hole/images/plate_hole_displ_mag.png
new file mode 100644
index 000000000..61a168d66
Binary files /dev/null and b/examples/python/solid_mechanics_model/plate-hole/images/plate_hole_displ_mag.png differ
diff --git a/examples/python/plate-hole/material.dat b/examples/python/solid_mechanics_model/plate-hole/material.dat
similarity index 100%
rename from examples/python/plate-hole/material.dat
rename to examples/python/solid_mechanics_model/plate-hole/material.dat
diff --git a/examples/python/plate-hole/plate.geo b/examples/python/solid_mechanics_model/plate-hole/plate.geo
similarity index 100%
rename from examples/python/plate-hole/plate.geo
rename to examples/python/solid_mechanics_model/plate-hole/plate.geo
diff --git a/examples/python/plate-hole/plate.py b/examples/python/solid_mechanics_model/plate-hole/plate.py
similarity index 100%
rename from examples/python/plate-hole/plate.py
rename to examples/python/solid_mechanics_model/plate-hole/plate.py
diff --git a/examples/python/solver_callback/CMakeLists.txt b/examples/python/solid_mechanics_model/solver_callback/CMakeLists.txt
similarity index 100%
rename from examples/python/solver_callback/CMakeLists.txt
rename to examples/python/solid_mechanics_model/solver_callback/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_model/solver_callback/README.rst b/examples/python/solid_mechanics_model/solver_callback/README.rst
new file mode 100644
index 000000000..4c3a287b6
--- /dev/null
+++ b/examples/python/solid_mechanics_model/solver_callback/README.rst
@@ -0,0 +1,34 @@
+solver_callback (2D)
+''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: solver_callback.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/solver_callback/solver_callback.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/solver_callback/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_model/`` `solver_callback <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_model/solver_callback/>`_
+
+
+In ``solver_callback``, it is shown how to write a solver callback function. It is done by writing a class that inherit
+from ``InterceptSolverCallback``::
+
+ class SolverCallback(aka.InterceptSolverCallback):
+ [.....]
+
+ solver_callback = SolverCallback(model)
+
+ model.solveStep(solver_callback)
+
+In that case, the solver callback is used to modify the stiffness matrix.
+
+
diff --git a/examples/python/solver_callback/bar.geo b/examples/python/solid_mechanics_model/solver_callback/bar.geo
similarity index 100%
rename from examples/python/solver_callback/bar.geo
rename to examples/python/solid_mechanics_model/solver_callback/bar.geo
diff --git a/examples/python/solver_callback/material.dat b/examples/python/solid_mechanics_model/solver_callback/material.dat
similarity index 100%
rename from examples/python/solver_callback/material.dat
rename to examples/python/solid_mechanics_model/solver_callback/material.dat
diff --git a/examples/python/solver_callback/solver_callback.py b/examples/python/solid_mechanics_model/solver_callback/solver_callback.py
similarity index 100%
rename from examples/python/solver_callback/solver_callback.py
rename to examples/python/solid_mechanics_model/solver_callback/solver_callback.py
diff --git a/examples/python/stiffness_matrix/CMakeLists.txt b/examples/python/solid_mechanics_model/stiffness_matrix/CMakeLists.txt
similarity index 100%
rename from examples/python/stiffness_matrix/CMakeLists.txt
rename to examples/python/solid_mechanics_model/stiffness_matrix/CMakeLists.txt
diff --git a/examples/python/solid_mechanics_model/stiffness_matrix/README.rst b/examples/python/solid_mechanics_model/stiffness_matrix/README.rst
new file mode 100644
index 000000000..0ee87aa36
--- /dev/null
+++ b/examples/python/solid_mechanics_model/stiffness_matrix/README.rst
@@ -0,0 +1,27 @@
+stiffness_matrix (2D)
+'''''''''''''''''''''
+
+:Sources:
+
+ .. collapse:: stiffness_matrix.py (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/stiffness_matrix/stiffness_matrix.py
+ :language: python
+ :lines: 9-
+
+ .. collapse:: material.dat (click to expand)
+
+ .. literalinclude:: examples/python/solid_mechanics_model/stiffness_matrix/material.dat
+ :language: text
+
+:Location:
+
+ ``examples/python/solid_mechanics_model/`` `stiffness_matrix <https://gitlab.com/akantu/akantu/-/blob/master/examples/python/solid_mechanics_model/stiffness_matrix/>`_
+
+
+``stiffness_matrix`` shows how to get the stiffness matrix from a mesh. It is done with::
+ model.assembleStiffnessMatrix()
+ K = model.getDOFManager().getMatrix('K')
+ stiff = aka.AkantuSparseMatrix(K).toarray()
+
+
diff --git a/examples/python/stiffness_matrix/material.dat b/examples/python/solid_mechanics_model/stiffness_matrix/material.dat
similarity index 100%
rename from examples/python/stiffness_matrix/material.dat
rename to examples/python/solid_mechanics_model/stiffness_matrix/material.dat
diff --git a/examples/python/stiffness_matrix/plate.geo b/examples/python/solid_mechanics_model/stiffness_matrix/plate.geo
similarity index 100%
rename from examples/python/stiffness_matrix/plate.geo
rename to examples/python/solid_mechanics_model/stiffness_matrix/plate.geo
diff --git a/examples/python/stiffness_matrix/plate.msh b/examples/python/solid_mechanics_model/stiffness_matrix/plate.msh
similarity index 100%
rename from examples/python/stiffness_matrix/plate.msh
rename to examples/python/solid_mechanics_model/stiffness_matrix/plate.msh
diff --git a/examples/python/stiffness_matrix/stiffness_matrix.py b/examples/python/solid_mechanics_model/stiffness_matrix/stiffness_matrix.py
similarity index 100%
rename from examples/python/stiffness_matrix/stiffness_matrix.py
rename to examples/python/solid_mechanics_model/stiffness_matrix/stiffness_matrix.py
diff --git a/examples/python/structural_mechanics/CMakeLists.txt b/examples/python/structural_mechanics_model/CMakeLists.txt
similarity index 100%
rename from examples/python/structural_mechanics/CMakeLists.txt
rename to examples/python/structural_mechanics_model/CMakeLists.txt
diff --git a/examples/python/structural_mechanics_model/images/displacements.png b/examples/python/structural_mechanics_model/images/displacements.png
new file mode 100644
index 000000000..a706f9df8
Binary files /dev/null and b/examples/python/structural_mechanics_model/images/displacements.png differ
diff --git a/examples/python/structural_mechanics_model/images/displacements_softening.png b/examples/python/structural_mechanics_model/images/displacements_softening.png
new file mode 100644
index 000000000..19955592f
Binary files /dev/null and b/examples/python/structural_mechanics_model/images/displacements_softening.png differ
diff --git a/examples/python/structural_mechanics/structural_mechanics.py b/examples/python/structural_mechanics_model/structural_mechanics.py
similarity index 100%
rename from examples/python/structural_mechanics/structural_mechanics.py
rename to examples/python/structural_mechanics_model/structural_mechanics.py
diff --git a/examples/python/structural_mechanics/structural_mechanics_dynamics.py b/examples/python/structural_mechanics_model/structural_mechanics_dynamics.py
similarity index 100%
rename from examples/python/structural_mechanics/structural_mechanics_dynamics.py
rename to examples/python/structural_mechanics_model/structural_mechanics_dynamics.py
diff --git a/examples/python/structural_mechanics/structural_mechanics_softening.py b/examples/python/structural_mechanics_model/structural_mechanics_softening.py
similarity index 100%
rename from examples/python/structural_mechanics/structural_mechanics_softening.py
rename to examples/python/structural_mechanics_model/structural_mechanics_softening.py
diff --git a/extra_packages/extra-materials/package.cmake b/extra_packages/extra-materials/package.cmake
index 5b5d5e7ff..425830518 100644
--- a/extra_packages/extra-materials/package.cmake
+++ b/extra_packages/extra-materials/package.cmake
@@ -1,116 +1,90 @@
#===============================================================================
# Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(extra_materials ADVANCED
DESCRIPTION "Add the extra list of materials in Akantu"
DEPENDS solid_mechanics)
package_declare_sources(extra_materials
material_extra_includes.hh
material_damage/material_brittle.cc
material_damage/material_brittle.hh
material_damage/material_brittle_inline_impl.hh
material_damage/material_damage_iterative.cc
material_damage/material_damage_iterative.hh
material_damage/material_damage_iterative_inline_impl.hh
material_damage/material_iterative_stiffness_reduction.cc
material_damage/material_iterative_stiffness_reduction.hh
material_damage/material_damage_linear.cc
material_damage/material_damage_linear.hh
material_damage/material_damage_linear_inline_impl.hh
material_damage/material_vreepeerlings.hh
material_damage/material_vreepeerlings_inline_impl.hh
material_damage/material_vreepeerlings_tmpl.hh
material_plastic/material_viscoplastic.cc
material_plastic/material_viscoplastic.hh
material_plastic/material_viscoplastic_inline_impl.hh
material_viscoelastic/material_stiffness_proportional.cc
material_viscoelastic/material_stiffness_proportional.hh
material_damage/material_orthotropic_damage.hh
material_damage/material_orthotropic_damage_tmpl.hh
material_damage/material_orthotropic_damage_iterative.cc
material_damage/material_orthotropic_damage_iterative.hh
material_damage/material_orthotropic_damage_iterative_inline_impl.hh
material_FE2/material_FE2.hh
material_FE2/material_FE2.cc
material_FE2/material_FE2_inline_impl.hh
material_FE2/solid_mechanics_model_RVE.hh
material_FE2/solid_mechanics_model_RVE.cc
)
-package_declare_material_infos(extra_materials
- LIST AKANTU_EXTRA_MATERIAL_LIST
- INCLUDE material_extra_includes.hh
- )
-
-package_declare_documentation_files(extra_materials
- manual-extra_materials.tex
- manual-appendix-materials-extra-materials.tex
-
- figures/stress_strain_visco.pdf
- )
-
-package_declare_documentation(extra_materials
- "This package activates additional constitutive laws:"
- "\\begin{itemize}"
- " \\item Linear anisotropy"
- " \\item Linear orthotropy"
- " \\item Visco-plastic"
- "\\end{itemize}"
- )
-
package_declare(extra_materials_non_local ADVANCED
DESCRIPTION "Add the extra list of non local materials in Akantu"
DEPENDS extra_materials damage_non_local)
package_declare_sources(extra_materials_non_local
material_damage/material_orthotropic_damage_non_local.hh
material_damage/material_vreepeerlings_non_local.cc
material_damage/material_vreepeerlings_non_local.hh
material_damage/material_brittle_non_local.hh
material_damage/material_damage_iterative_non_local.hh
material_damage/material_damage_iterative_non_local.cc
material_damage/material_orthotropic_damage_iterative_non_local.hh
material_damage/material_vreepeerlings_non_local_inline_impl.hh
material_damage/material_brittle_non_local_inline_impl.hh
material_damage/material_damage_iterative_non_local_inline_impl.hh
material_damage/material_orthotropic_damage_iterative_non_local_inline_impl.hh
material_non_local_extra_includes.hh
)
-
-package_declare_material_infos(extra_materials_non_local
- LIST AKANTU_DAMAGE_NON_LOCAL_MATERIAL_EXTRA_LIST
- INCLUDE material_extra_includes.hh
- )
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 06144882a..6e9688ba1 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,596 +1,596 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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<Idx> & filter_map = mat.getElementFilter();
// Loop over all element types
for (auto && type : filter_map.elementTypes(spatial_dimension)) {
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 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);
+ this->synchronize(SynchronizationTag::_constitutive_law_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);
+ this->synchronize(SynchronizationTag::_clh_init_cl);
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/igfem/package.cmake b/extra_packages/igfem/package.cmake
index 012c1de01..cace7183b 100644
--- a/extra_packages/igfem/package.cmake
+++ b/extra_packages/igfem/package.cmake
@@ -1,84 +1,79 @@
#===============================================================================
# Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(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_material_infos(igfem
- LIST AKANTU_IGFEM_MATERIAL_LIST
- INCLUDE material_igfem_includes.hh
- )
diff --git a/extra_packages/igfem/src/material_igfem/material_igfem_inline_impl.hh b/extra_packages/igfem/src/material_igfem/material_igfem_inline_impl.hh
index 9a4935734..7ecaa94d8 100644
--- a/extra_packages/igfem/src/material_igfem/material_igfem_inline_impl.hh
+++ b/extra_packages/igfem/src/material_igfem/material_igfem_inline_impl.hh
@@ -1,66 +1,65 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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
#include "igfem_helper.hh"
#include "solid_mechanics_model_igfem.hh"
#include <iostream>
namespace akantu {
/* -------------------------------------------------------------------------- */
inline UInt MaterialIGFEM::getNbDataForElements(const Array<Element> & elements,
SynchronizationTag tag) const {
if (tag == SynchronizationTag::_smm_stress) {
return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension *
spatial_dimension * sizeof(Real) *
this->getModel().getNbIntegrationPoints(elements, "IGFEMFEEngine");
}
return 0;
}
/* -------------------------------------------------------------------------- */
inline void MaterialIGFEM::packElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) const {
if (tag == SynchronizationTag::_smm_stress) {
if (this->isFiniteDeformation()) {
- packElementDataHelper(piola_kirchhoff_2, buffer, elements,
+ packInternalFieldHelper(piola_kirchhoff_2, buffer, elements,
"IGFEMFEEngine");
- packElementDataHelper(gradu, buffer, elements, "IGFEMFEEngine");
+ packInternalFieldHelper(gradu, buffer, elements, "IGFEMFEEngine");
}
- packElementDataHelper(stress, buffer, elements, "IGFEMFEEngine");
+ packInternalFieldHelper(stress, buffer, elements, "IGFEMFEEngine");
}
}
/* -------------------------------------------------------------------------- */
inline void MaterialIGFEM::unpackElementData(CommunicationBuffer & buffer,
const Array<Element> & elements,
SynchronizationTag tag) {
if (tag == SynchronizationTag::_smm_stress) {
if (this->isFiniteDeformation()) {
- unpackElementDataHelper(piola_kirchhoff_2, buffer, elements,
- "IGFEMFEEngine");
- unpackElementDataHelper(gradu, buffer, elements, "IGFEMFEEngine");
+ unpackInternalFieldHelper(piola_kirchhoff_2, buffer, elements);
+ unpackInternalFieldHelper(gradu, buffer, elements);
}
- unpackElementDataHelper(stress, buffer, elements, "IGFEMFEEngine");
+ unpackInternalFieldHelper(stress, buffer, elements);
}
}
diff --git a/packages/boost.cmake b/packages/boost.cmake
index 38246ccb5..e27959833 100644
--- a/packages/boost.cmake
+++ b/packages/boost.cmake
@@ -1,49 +1,49 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(Boost_NO_BOOST_CMAKE ON CACHE BOOL "" FORCE)
package_declare(Boost EXTERNAL
NOT_OPTIONAL
DESCRIPTION "Package handling boost components"
- EXTRA_PACKAGE_OPTIONS PREFIX Boost
+ EXTRA_PACKAGE_OPTIONS TARGET Boost::headers
)
mask_package_options(Boost)
mark_as_advanced(AKANTU_USE_BOOST)
package_on_enabled_script(Boost
"if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER \"4.8\")
set(_boost_version \${Boost_MAJOR_VERSION}.\${Boost_MINOR_VERSION})
if(_boost_version VERSION_LESS 1.58 AND _boost_version VERSION_GREATER 1.53)
package_set_compile_flags(Boost CXX -DBOOST_SPIRIT_USE_PHOENIX_V3)
else()
package_unset_compile_flags(Boost CXX)
endif()
endif()
")
package_set_package_system_dependency(Boost deb-src libboost-dev)
# only build dependency
# package_set_package_system_dependency(Boost deb libboost)
# package_set_package_system_dependency(Boost rmp boost)
diff --git a/packages/cohesive_element.cmake b/packages/cohesive_element.cmake
index f7ebf7d9f..86c8a49d8 100644
--- a/packages/cohesive_element.cmake
+++ b/packages/cohesive_element.cmake
@@ -1,75 +1,70 @@
#===============================================================================
# Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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 DEFAULT ON
DESCRIPTION "Use cohesive_element package of Akantu"
DEPENDS 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_material_infos(cohesive_element
- LIST AKANTU_COHESIVE_MATERIAL_LIST
- INCLUDE material_cohesive_includes.hh
- )
diff --git a/packages/contact_mechanics.cmake b/packages/contact_mechanics.cmake
index f9b8eadd6..ad2dc611a 100644
--- a/packages/contact_mechanics.cmake
+++ b/packages/contact_mechanics.cmake
@@ -1,65 +1,65 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(contact_mechanics DEFAULT ON
DEPENDS model_couplers cohesive_element
DESCRIPTION "Use Contact Mechanics package of Akantu")
package_declare_sources(contact_mechanics
model/contact_mechanics/contact_mechanics_model.hh
model/contact_mechanics/contact_mechanics_model.cc
model/contact_mechanics/contact_detector.hh
model/contact_mechanics/contact_detector.cc
- model/contact_mechanics/contact_detector_inline_impl.cc
+ model/contact_mechanics/contact_detector_inline_impl.hh
model/contact_mechanics/contact_element.hh
model/contact_mechanics/geometry_utils.hh
model/contact_mechanics/geometry_utils.cc
- model/contact_mechanics/geometry_utils_inline_impl.cc
+ model/contact_mechanics/geometry_utils_inline_impl.hh
model/contact_mechanics/resolution.hh
model/contact_mechanics/resolution.cc
model/contact_mechanics/resolution_utils.hh
model/contact_mechanics/resolution_utils.cc
model/contact_mechanics/resolutions/resolution_penalty.hh
model/contact_mechanics/resolutions/resolution_penalty.cc
model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
model/contact_mechanics/resolutions/resolution_penalty_quadratic.cc
model/contact_mechanics/surface_selector.hh
model/contact_mechanics/surface_selector.cc
model/model_couplers/coupler_solid_contact.hh
model/model_couplers/coupler_solid_contact_tmpl.hh
model/model_couplers/coupler_solid_contact.cc
model/model_couplers/coupler_solid_cohesive_contact.hh
model/model_couplers/coupler_solid_cohesive_contact.cc
model/model_couplers/cohesive_contact_solvercallback.hh
model/model_couplers/cohesive_contact_solvercallback.cc
)
package_declare_documentation_files(contact_mechanics
manual-contactmechanicsmodel.tex
manual-contact-detector.tex
)
package_declare_documentation(contact_mechanics
"This package activates the contact mechanics model")
diff --git a/packages/core.cmake b/packages/core.cmake
index dc7457029..e70c826c8 100644
--- a/packages/core.cmake
+++ b/packages/core.cmake
@@ -1,356 +1,370 @@
#===============================================================================
# Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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"
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 CXX "-Wall -Wextra -pedantic")
else()
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))
+if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.9) OR
+ (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 14.0))
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_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/constitutive_laws/constitutive_law_non_local_interface.hh
+ model/common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh
+ model/common/constitutive_laws/constitutive_law.hh
+ model/common/constitutive_laws/constitutive_law_selector.hh
+ model/common/constitutive_laws/constitutive_law_selector_tmpl.hh
+ model/common/constitutive_laws/constitutive_law_tmpl.hh
+ model/common/constitutive_laws/constitutive_laws_handler.hh
+ model/common/constitutive_laws/constitutive_laws_handler_tmpl.hh
+ model/common/constitutive_laws/internal_field.hh
+ model/common/constitutive_laws/internal_field_tmpl.hh
+ model/common/constitutive_laws/random_internal_field.hh
+ model/common/constitutive_laws/random_internal_field_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_linear.cc
+ model/common/non_linear_solver/non_linear_solver_linear.hh
model/common/non_linear_solver/non_linear_solver_lumped.cc
model/common/non_linear_solver/non_linear_solver_lumped.hh
+ model/common/non_linear_solver/non_linear_solver_newton_raphson.cc
+ model/common/non_linear_solver/non_linear_solver_newton_raphson.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_eigen.cc
+ solver/sparse_solver_eigen.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/data_accessor_tmpl.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
)
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
)
diff --git a/packages/damage_non_local.cmake b/packages/damage_non_local.cmake
index 49a10ecda..4579be9fb 100644
--- a/packages/damage_non_local.cmake
+++ b/packages/damage_non_local.cmake
@@ -1,52 +1,47 @@
#===============================================================================
# Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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")
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/heat_transfer.cmake b/packages/diffusion.cmake
similarity index 70%
rename from packages/heat_transfer.cmake
rename to packages/diffusion.cmake
index 2ee4972de..3424727cf 100644
--- a/packages/heat_transfer.cmake
+++ b/packages/diffusion.cmake
@@ -1,29 +1,34 @@
#===============================================================================
# Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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 DEFAULT ON
- DESCRIPTION "Use Heat Transfer package of Akantu")
+package_declare(diffusion DEFAULT ON
+ DESCRIPTION "Activate Diffusion model of Akantu")
-package_declare_sources(heat_transfer
- model/heat_transfer/heat_transfer_model.cc
- model/heat_transfer/heat_transfer_model.hh
+package_declare_sources(diffusion
+ model/diffusion_model/heat_transfer_model.hh
+ model/diffusion_model/diffusion_model.cc
+ model/diffusion_model/diffusion_model.hh
+ model/diffusion_model/diffusion_law.cc
+ model/diffusion_model/diffusion_law.hh
+ model/diffusion_model/heat_diffusion.cc
+ model/diffusion_model/heat_diffusion.hh
)
diff --git a/packages/embedded.cmake b/packages/embedded.cmake
index 274720f46..30888424a 100644
--- a/packages/embedded.cmake
+++ b/packages/embedded.cmake
@@ -1,42 +1,35 @@
#===============================================================================
# Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(embedded
DESCRIPTION "Add support for the embedded solid mechanics model"
DEPENDS CGAL)
package_declare_sources(embedded
model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc
model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.hh
model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc
model/solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.hh
- model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
model/solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh
)
-
-package_declare_material_infos(embedded
- LIST AKANTU_EMBEDDED_MATERIAL_LIST
- INCLUDE material_embedded_includes.hh
- )
-
diff --git a/packages/implicit.cmake b/packages/implicit.cmake
index c9e112241..3b879e342 100644
--- a/packages/implicit.cmake
+++ b/packages/implicit.cmake
@@ -1,47 +1,56 @@
#===============================================================================
# Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(implicit META
DESCRIPTION "Add support for implicit time scheme")
+
set(AKANTU_IMPLICIT_SOLVER "Mumps"
CACHE STRING "Solver activated in Akantu")
+
set_property(CACHE AKANTU_IMPLICIT_SOLVER PROPERTY STRINGS
+ Eigen
Mumps
PETSc
Mumps+PETSc
- )
+)
+
+package_is_activated(parallel _is_parallel)
+
+if(_is_parallel AND AKANTU_IMPLICIT_SOLVER MATCHES "Eigen")
+ message(WARNING "The Eigen solver does not work in parallel")
+endif()
if(AKANTU_IMPLICIT_SOLVER MATCHES "Mumps")
package_add_dependencies(implicit PRIVATE Mumps)
else()
package_remove_dependencies(implicit Mumps)
set(AKANTU_USE_MUMPS OFF CACHE BOOL "" FORCE)
endif()
if(AKANTU_IMPLICIT_SOLVER MATCHES "PETSc")
package_add_dependencies(implicit
PRIVATE PETSc)
else()
package_remove_dependency(implicit PETSc)
set(AKANTU_USE_PETSC OFF CACHE BOOL "" FORCE)
endif()
diff --git a/packages/solid_mechanics.cmake b/packages/solid_mechanics.cmake
index ad1181ce0..d970a7713 100644
--- a/packages/solid_mechanics.cmake
+++ b/packages/solid_mechanics.cmake
@@ -1,110 +1,90 @@
#===============================================================================
# Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(solid_mechanics DEFAULT ON
DESCRIPTION "Solid mechanics model"
DEPENDS core
)
package_declare_sources(solid_mechanics
model/solid_mechanics/material.cc
model/solid_mechanics/material.hh
model/solid_mechanics/material_inline_impl.hh
model/solid_mechanics/material_selector.hh
model/solid_mechanics/material_selector_tmpl.hh
- model/solid_mechanics/materials/internal_field.hh
- model/solid_mechanics/materials/internal_field_tmpl.hh
- model/solid_mechanics/materials/random_internal_field.hh
- model/solid_mechanics/materials/random_internal_field_tmpl.hh
model/solid_mechanics/solid_mechanics_model.cc
model/solid_mechanics/solid_mechanics_model.hh
- model/solid_mechanics/solid_mechanics_model_inline_impl.hh
model/solid_mechanics/solid_mechanics_model_io.cc
model/solid_mechanics/solid_mechanics_model_mass.cc
- model/solid_mechanics/solid_mechanics_model_material.cc
- model/solid_mechanics/solid_mechanics_model_tmpl.hh
model/solid_mechanics/solid_mechanics_model_event_handler.hh
model/solid_mechanics/materials/plane_stress_toolbox.hh
model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
- model/solid_mechanics/materials/material_core_includes.hh
model/solid_mechanics/materials/material_elastic.cc
model/solid_mechanics/materials/material_elastic.hh
model/solid_mechanics/materials/material_elastic_inline_impl.hh
model/solid_mechanics/materials/material_thermal.cc
model/solid_mechanics/materials/material_thermal.hh
model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
model/solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh
model/solid_mechanics/materials/material_elastic_orthotropic.cc
model/solid_mechanics/materials/material_elastic_orthotropic.hh
model/solid_mechanics/materials/material_damage/material_anisotropic_damage.hh
model/solid_mechanics/materials/material_damage/material_anisotropic_damage.cc
model/solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh
model/solid_mechanics/materials/material_damage/material_damage.hh
model/solid_mechanics/materials/material_damage/material_damage_tmpl.hh
model/solid_mechanics/materials/material_damage/material_marigo.cc
model/solid_mechanics/materials/material_damage/material_marigo.hh
model/solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh
model/solid_mechanics/materials/material_damage/material_mazars.cc
model/solid_mechanics/materials/material_damage/material_mazars.hh
model/solid_mechanics/materials/material_damage/material_phasefield.cc
model/solid_mechanics/materials/material_damage/material_phasefield.hh
model/solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh
model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc
model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic.hh
model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh
model/solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh
model/solid_mechanics/materials/material_finite_deformation/material_neohookean.cc
model/solid_mechanics/materials/material_finite_deformation/material_neohookean.hh
model/solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh
model/solid_mechanics/materials/material_plastic/material_plastic.cc
model/solid_mechanics/materials/material_plastic/material_plastic.hh
model/solid_mechanics/materials/material_plastic/material_plastic_inline_impl.hh
model/solid_mechanics/materials/material_plastic/material_drucker_prager.cc
model/solid_mechanics/materials/material_plastic/material_drucker_prager.hh
model/solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh
model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc
model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.hh
model/solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh
model/solid_mechanics/materials/material_damage/material_von_mises_mazars.cc
model/solid_mechanics/materials/material_damage/material_von_mises_mazars.hh
model/solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh
model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc
model/solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.hh
model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc
model/solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh
model/solid_mechanics/materials/material_non_local.hh
- model/solid_mechanics/materials/material_non_local_tmpl.hh
- model/solid_mechanics/materials/material_non_local_includes.hh
- )
-
-package_declare_material_infos(solid_mechanics
- LIST AKANTU_CORE_MATERIAL_LIST
- INCLUDE material_core_includes.hh
- )
-
-package_declare_extra_files_to_package(solid_mechanics
- SOURCES
- model/solid_mechanics/material_list.hh.in
)
diff --git a/packages/z_mumps.cmake b/packages/z_mumps.cmake
index ebbbb2231..916cc2e92 100644
--- a/packages/z_mumps.cmake
+++ b/packages/z_mumps.cmake
@@ -1,65 +1,61 @@
#===============================================================================
# Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(Mumps EXTERNAL
DESCRIPTION "Add Mumps support in akantu"
)
package_declare_sources(Mumps
- model/common/non_linear_solver/non_linear_solver_linear.cc
- model/common/non_linear_solver/non_linear_solver_linear.hh
- model/common/non_linear_solver/non_linear_solver_newton_raphson.cc
- model/common/non_linear_solver/non_linear_solver_newton_raphson.hh
solver/sparse_solver_mumps.cc
solver/sparse_solver_mumps.hh
)
set(_mumps_float_type ${AKANTU_FLOAT_TYPE})
if(AKANTU_FLOAT_TYPE STREQUAL "float" OR
AKANTU_FLOAT_TYPE STREQUAL "double")
set(_mumps_components ${AKANTU_FLOAT_TYPE})
else()
if(DEFINED AKANTU_FLOAT_TYPE)
message(FATAL_ERROR "MUMPS does not support floating point type \"${AKANTU_FLOAT_TYPE}\"")
endif()
endif()
package_get_option_name(parallel _par_option)
if(${_par_option})
list(APPEND _mumps_components "parallel")
package_set_package_system_dependency(Mumps deb libmumps)
package_set_package_system_dependency(Mumps deb-src libmumps-dev)
package_add_dependencies(Mumps PRIVATE parallel)
else()
list(APPEND _mumps_components "sequential")
package_set_package_system_dependency(Mumps deb libmumps-seq)
package_set_package_system_dependency(Mumps deb-src libmumps-seq-dev)
package_remove_dependencies(Mumps PRIVATE parallel)
endif()
package_set_find_package_extra_options(Mumps ARGS COMPONENTS "${_mumps_components}")
package_declare_extra_files_to_package(Mumps
PROJECT
cmake/Modules/FindMumps.cmake
)
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index e53b19377..603658d7a 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -1,138 +1,139 @@
#===============================================================================
# Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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(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_constitutive_law.cc
+ py_constitutive_law_selector.cc
py_dof_manager.cc
+ py_dumpable.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)
+package_is_activated(diffusion _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/py_aka_array.hh b/python/py_aka_array.hh
index c3a594dd3..0b38106fd 100644
--- a/python/py_aka_array.hh
+++ b/python/py_aka_array.hh
@@ -1,224 +1,229 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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>
/* -------------------------------------------------------------------------- */
+#ifndef AKANTU_PY_AKA_ARRAY_HH_
+#define AKANTU_PY_AKA_ARRAY_HH_
+
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<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(Int /*size*/, Int /*nb_component*/) final {}
// allocate and initialize the memory
void allocate(Int /*size*/, Int /*nb_component*/,
const T & /*value*/) final {}
public:
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.data();
this->size_ = src.size();
this->nb_component = src.getNbComponent();
}
~ArrayProxy() override { this->values = nullptr; }
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(Int new_size) final {
if (new_size != this->size()) {
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<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 U> using array_type_t = typename AkaArrayType<U>::type;
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.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
+
+#endif /* AKANTU_PY_AKA_ARRAY_HH_ */
diff --git a/python/py_aka_error.cc b/python/py_aka_error.cc
index 4f6ed48ef..0fe5ef4d1 100644
--- a/python/py_aka_error.cc
+++ b/python/py_aka_error.cc
@@ -1,83 +1,82 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_error.hh"
/* -------------------------------------------------------------------------- */
#include <aka_error.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
void register_error(py::module & mod) {
+ py::enum_<DebugLevel>(mod, "DebugLevel")
+ .value("dblError", dblError)
+ .value("dblException", dblException)
+ .value("dblCritical", dblCritical)
+ .value("dblMajor", dblMajor)
+ .value("dblWarning", dblWarning)
+ .value("dblInfo", dblInfo)
+ .value("dblTrace", dblTrace)
+ .value("dblAccessory", dblAccessory)
+ .value("dblDebug", dblDebug)
+ .value("dblDump", dblDump)
+ .value("dblTest", dblTest)
+ .export_values();
py::module mod_debug = mod.def_submodule("debug");
mod.def("setDebugLevel", [](DebugLevel lvl) {
debug::setDebugLevel(lvl);
PyErr_WarnEx(PyExc_DeprecationWarning,
"setDebugLevel() is deprecated, it has moved in the "
"submodule debug",
1);
});
mod.def("getDebugLevel", []() {
PyErr_WarnEx(PyExc_DeprecationWarning,
"getDebugLevel() is deprecated, it has moved in the "
"submodule debug",
1);
return debug::getDebugLevel();
});
mod.def("printBacktrace", [](bool flag) {
debug::debugger.printBacktrace(flag);
PyErr_WarnEx(PyExc_DeprecationWarning,
"printBacktrace() is deprecated, it has moved in the "
"submodule debug",
1);
});
mod_debug.def("setDebugLevel", &debug::setDebugLevel);
mod_debug.def("getDebugLevel", &debug::getDebugLevel);
mod_debug.def("printBacktrace",
[](bool flag) { debug::debugger.printBacktrace(flag); });
-
- py::enum_<DebugLevel>(mod, "DebugLevel")
- .value("dblError", dblError)
- .value("dblException", dblException)
- .value("dblCritical", dblCritical)
- .value("dblMajor", dblMajor)
- .value("dblWarning", dblWarning)
- .value("dblInfo", dblInfo)
- .value("dblTrace", dblTrace)
- .value("dblAccessory", dblAccessory)
- .value("dblDebug", dblDebug)
- .value("dblDump", dblDump)
- .value("dblTest", dblTest)
- .export_values();
}
} // namespace akantu
diff --git a/python/py_akantu.cc b/python/py_akantu.cc
index 08613e3c2..071814a72 100644
--- a/python/py_akantu.cc
+++ b/python/py_akantu.cc
@@ -1,166 +1,169 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
// for NLSNotConvergedException
#include "non_linear_solver.hh"
/* -------------------------------------------------------------------------- */
#include "py_aka_common.hh"
#include "py_aka_error.hh"
#include "py_boundary_conditions.hh"
+#include "py_constitutive_law.hh"
+#include "py_constitutive_law_selector.hh"
#include "py_dof_manager.hh"
#include "py_dumpable.hh"
#include "py_fe_engine.hh"
#include "py_group_manager.hh"
#include "py_integration_scheme.hh"
#include "py_mesh.hh"
#include "py_model.hh"
#include "py_parser.hh"
#include "py_solver.hh"
#if defined(AKANTU_SOLID_MECHANICS)
#include "py_material.hh"
-#include "py_material_selector.hh"
#include "py_solid_mechanics_model.hh"
#endif
-#if defined(AKANTU_HEAT_TRANSFER)
+#if defined(AKANTU_DIFFUSION)
#include "py_heat_transfer_model.hh"
#endif
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "py_fragment_manager.hh"
#include "py_solid_mechanics_model_cohesive.hh"
#endif
#if defined(AKANTU_CONTACT_MECHANICS)
#include "py_contact_mechanics_model.hh"
#include "py_model_couplers.hh"
#endif
#if defined(AKANTU_PHASE_FIELD)
#include "py_phase_field_model.hh"
#endif
#if defined(AKANTU_STRUCTURAL_MECHANICS)
#include "py_structural_mechanics_model.hh"
#endif
/* -------------------------------------------------------------------------- */
#include <aka_error.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
#include <iostream>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
namespace akantu {
void register_all(pybind11::module & mod) {
register_initialize(mod);
register_enums(mod);
register_error(mod);
register_functions(mod);
register_parser(mod);
register_solvers(mod);
register_group_manager(mod);
register_dumpable(mod);
register_mesh(mod);
register_fe_engine(mod);
register_integration_schemes(mod);
register_dof_manager(mod);
register_boundary_conditions(mod);
register_model(mod);
-#if defined(AKANTU_HEAT_TRANSFER)
+ register_constitutive_law_selector(mod);
+ register_constitutive_law_internal_handler(mod);
+
+#if defined(AKANTU_DIFFUSION)
register_heat_transfer_model(mod);
#endif
#if defined(AKANTU_SOLID_MECHANICS)
register_solid_mechanics_model(mod);
register_material(mod);
- register_material_selector(mod);
#endif
#if defined(AKANTU_COHESIVE_ELEMENT)
register_solid_mechanics_model_cohesive(mod);
register_fragment_manager(mod);
#endif
#if defined(AKANTU_STRUCTURAL_MECHANICS)
register_structural_mechanics_model(mod);
#endif
#if defined(AKANTU_CONTACT_MECHANICS)
register_contact_mechanics_model(mod);
register_model_couplers(mod);
#endif
#if defined(AKANTU_PHASE_FIELD)
register_phase_field_model(mod);
register_phase_field_coupler(mod);
#endif
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
PYBIND11_MODULE(py11_akantu, mod) {
mod.doc() = "Akantu python interface";
static py::exception<akantu::debug::Exception> akantu_exception(mod,
"Exception");
static py::exception<akantu::debug::NLSNotConvergedException>
akantu_exception_nls_not_converged(mod, "NLSNotConvergedException");
py::register_exception_translator([](std::exception_ptr ptr) {
try {
if (ptr) {
std::rethrow_exception(ptr);
}
} catch (akantu::debug::NLSNotConvergedException & e) {
akantu_exception_nls_not_converged(e.info().c_str());
} catch (akantu::debug::Exception & e) {
if (akantu::debug::debugger.printBacktrace()) {
akantu::debug::printBacktrace();
}
akantu_exception(e.info().c_str());
}
});
akantu::register_all(mod);
mod.def("has_mpi",
[]() {
#if defined(AKANTU_USE_MPI)
return true;
#else
return false;
#endif
})
.def("getVersion", &akantu::getVersion);
} // Module akantu
diff --git a/python/py_constitutive_law.cc b/python/py_constitutive_law.cc
new file mode 100644
index 000000000..c8225361c
--- /dev/null
+++ b/python/py_constitutive_law.cc
@@ -0,0 +1,145 @@
+/**
+ * @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_constitutive_law.hh"
+#include "py_aka_array.hh"
+#include "py_akantu_pybind11_compatibility.hh"
+/* -------------------------------------------------------------------------- */
+#include <constitutive_law.hh>
+#include <constitutive_laws_handler.hh>
+#include <parsable.hh>
+/* -------------------------------------------------------------------------- */
+#include <pybind11/operators.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+/* -------------------------------------------------------------------------- */
+namespace py = pybind11;
+/* -------------------------------------------------------------------------- */
+
+namespace akantu {
+
+namespace {
+ /* ------------------------------------------------------------------------ */
+ 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(), py::multiple_inheritance())
+ .def(
+ "previous",
+ [](InternalField<T> & self, ElementType type, GhostType ghost_type)
+ -> Array<T> & { return self.previous(type, ghost_type); },
+ py::arg("type"), py::arg("ghost_type") = _not_ghost,
+ py::return_value_policy::reference)
+ .def(
+ "previous",
+ [](InternalField<T> & self) -> InternalField<T> & {
+ return self.previous();
+ },
+ py::return_value_policy::reference)
+ .def(
+ "__call__",
+ [](InternalField<T> & self, ElementType type, GhostType ghost_type)
+ -> Array<T> & { return self(type, ghost_type); },
+ py::arg("type"), py::arg("ghost_type") = _not_ghost,
+ py::return_value_policy::reference)
+ .def("__repr__",
+ [name](const InternalField<T> & self) {
+ std::stringstream sstream;
+ sstream << std::hex << &self;
+
+ std::string str{"<InternalField" + name + " (0x" +
+ sstream.str() + "): " + self.getRegisterID() +
+ " "};
+ for (auto && ghost_type : ghost_types) {
+ for (auto && type : self.elementTypes(ghost_type)) {
+ const auto & array = self(type, ghost_type);
+ if (str.back() == ']') {
+ str += ", ";
+ }
+ str += "[" + std::to_string(type) + ":" +
+ std::to_string(ghost_type) + " - Array<" +
+ debug::demangle<T>() + " " +
+ std::to_string(array.size()) + ", " +
+ std::to_string(array.getNbComponent()) + ">]";
+ }
+ }
+ str += ">";
+ return str;
+ })
+ .def(
+ "getID", [](InternalField<T> & self) { return self.getID(); },
+ py::return_value_policy::copy)
+ .def("initializeHistory", &InternalField<T>::initializeHistory)
+ .def("hasHistory", &InternalField<T>::hasHistory);
+ }
+} // namespace
+
+/* -------------------------------------------------------------------------- */
+void register_constitutive_law_internal_handler(py::module & mod) {
+ register_internal_field<Real>(mod, "Real");
+ register_internal_field<Int>(mod, "Int");
+
+ py::class_<ConstitutiveLawInternalHandler>(
+ mod, "ConstitutiveLawInternalHandler", py::multiple_inheritance())
+ .def(py::init<const ID &, Int, const ID &>())
+ .def("registerInternalReal",
+ [](ConstitutiveLawInternalHandler & self, const std::string & name,
+ Int nb_component) -> decltype(auto) {
+ self.registerInternal<Real>(name, nb_component);
+ return self.getSharedPtrInternal<Real>(name);
+ })
+ .def("registerInternalInt",
+ [](ConstitutiveLawInternalHandler & self, const std::string & name,
+ UInt nb_component) -> decltype(auto) {
+ self.template registerInternal<Int>(name, nb_component);
+ return self.getSharedPtrInternal<Int>(name);
+ })
+ .def("getInternalReal",
+ [](ConstitutiveLawInternalHandler & self,
+ const ID & id) -> decltype(auto) {
+ return self.getSharedPtrInternal<Real>(id);
+ })
+ .def("getInternalInt",
+ [](ConstitutiveLawInternalHandler & self, const ID & id)
+ -> decltype(auto) { return self.getSharedPtrInternal<Int>(id); })
+ .def("getElementFilter",
+ [](const ConstitutiveLawInternalHandler & self) -> decltype(auto) {
+ return self.getElementFilterSharedPtr();
+ })
+ .def("getSpatialDimension",
+ &ConstitutiveLawInternalHandler::getSpatialDimension);
+}
+
+} // namespace akantu
diff --git a/python/py_constitutive_law.hh b/python/py_constitutive_law.hh
new file mode 100644
index 000000000..3fd6cfe6b
--- /dev/null
+++ b/python/py_constitutive_law.hh
@@ -0,0 +1,98 @@
+#include "py_aka_array.hh"
+#include "py_akantu_pybind11_compatibility.hh"
+/* -------------------------------------------------------------------------- */
+#include <constitutive_law.hh>
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_PY_CONSTITUTIVE_LAW_HH_
+#define AKANTU_PY_CONSTITUTIVE_LAW_HH_
+
+namespace akantu {
+
+void register_constitutive_law_internal_handler(pybind11::module & mod);
+
+template <class ConstitutiveLawHandler>
+class PyConstitutiveLaw : public ConstitutiveLaw<ConstitutiveLawHandler> {
+public:
+ using Parent = ConstitutiveLaw<ConstitutiveLawHandler>;
+ /* Inherit the constructors */
+ using Parent::Parent;
+
+ ~PyConstitutiveLaw() override = default;
+
+ void initConstitutiveLaw() override {
+ // NOLINTNEXTLINE
+ PYBIND11_OVERRIDE(void, Parent, initConstitutiveLaw, );
+ }
+
+ Real getEnergy(const ID & energy_id) override {
+ // NOLINTNEXTLINE
+ PYBIND11_OVERRIDE(Real, Parent, getEnergy, energy_id);
+ }
+ Real getEnergy(const ID & energy_id, const Element & element) override {
+ // NOLINTNEXTLINE
+ PYBIND11_OVERRIDE(Real, Parent, getEnergy, energy_id, element);
+ }
+
+ // methods need to be defined to be able to do the python interface
+ Int 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{};
+};
+
+/* ------------------------------------------------------------------------ */
+template <class ConstitutiveLawsHandler_>
+void register_constitutive_law(py::module & mod) {
+ using CL = ConstitutiveLaw<ConstitutiveLawsHandler_>;
+ const std::string & name =
+ "ConstitutiveLaw" + debug::demangle<ConstitutiveLawsHandler_>();
+
+ py::class_<CL, ConstitutiveLawInternalHandler, Parsable,
+ PyConstitutiveLaw<ConstitutiveLawsHandler_>>(
+ mod, name.c_str(), py::multiple_inheritance())
+ .def(py::template init<ConstitutiveLawsHandler_ &, const ID &, Int,
+ ElementKind, const ID &>())
+ /*
+ * These functions override the `Parsable` interface.
+ * This ensure that the `updateInternalParameters()` function is called.
+ */
+ .def(
+ "setReal",
+ [](CL & self, const ID & name, const Real value) -> void {
+ self.setParam(name, value);
+ return;
+ },
+ py::arg("name"), py::arg("value"))
+ .def(
+ "setBool",
+ [](CL & self, const ID & name, const bool value) -> void {
+ self.setParam(name, value);
+ return;
+ },
+ py::arg("name"), py::arg("value"))
+ .def(
+ "setString",
+ [](CL & self, const ID & name, const std::string & value) -> void {
+ self.setParam(name, value);
+ return;
+ },
+ py::arg("name"), py::arg("value"))
+ .def(
+ "setInt",
+ [](CL & self, const ID & name, const int value) -> void {
+ self.setParam(name, value);
+ return;
+ },
+ py::arg("name"), py::arg("value"));
+}
+
+} // namespace akantu
+
+#endif // AKANTU_PY_CONSTITUTIVE_LAW_HH_
diff --git a/python/py_material_selector.cc b/python/py_constitutive_law_selector.cc
similarity index 64%
rename from python/py_material_selector.cc
rename to python/py_constitutive_law_selector.cc
index 3a4b4f27f..dd5ed518f 100644
--- a/python/py_material_selector.cc
+++ b/python/py_constitutive_law_selector.cc
@@ -1,106 +1,118 @@
/**
- * Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ * @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
*
- * This file is part of Akantu
+ *
+ * @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 "py_constitutive_law_selector.hh"
/* -------------------------------------------------------------------------- */
+#include <constitutive_law_selector.hh>
+#if defined(AKANTU_SOLID_MECHANICS)
#include <material_selector.hh>
#include <solid_mechanics_model.hh>
+#endif
#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 {
+ template <class Base = ConstitutiveLawSelector>
+ class PyConstitutiveLawSelector : public Base {
public:
/* Inherit the constructors */
using Base::Base;
- ~PyMaterialSelector() override = default;
-
Idx operator()(const Element & element) override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE_NAME(Idx, MaterialSelector, "__call__", operator(),
- element);
+ PYBIND11_OVERRIDE_NAME(Idx, ConstitutiveLawSelector,
+ "__call__", operator(), element);
}
};
- template <class MaterialSelectorDaughter>
+ template <class ConstitutiveLawSelectorDaughter>
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());
+ return py::class_<
+ ConstitutiveLawSelectorDaughter, ConstitutiveLawSelector,
+ PyConstitutiveLawSelector<ConstitutiveLawSelectorDaughter>,
+ std::shared_ptr<ConstitutiveLawSelectorDaughter>>(mod,
+ class_name.c_str());
}
} // namespace
-void register_material_selector(py::module & mod) {
- py::class_<MaterialSelector, PyMaterialSelector<>,
- std::shared_ptr<MaterialSelector>>(mod, "MaterialSelector")
+void register_constitutive_law_selector(py::module & mod) {
+ py::class_<ConstitutiveLawSelector, PyConstitutiveLawSelector<>,
+ std::shared_ptr<ConstitutiveLawSelector>>(
+ mod, "ConstitutiveLawSelector")
.def(py::init())
.def("setFallback",
- [](MaterialSelector & self, UInt f) { self.setFallback(f); })
+ [](ConstitutiveLawSelector & self, Int f) { self.setFallback(f); })
.def("setFallback",
- [](MaterialSelector & self,
- const std::shared_ptr<MaterialSelector> & fallback_selector) {
- self.setFallback(fallback_selector);
- })
- .def("__call__", &MaterialSelector::operator());
+ [](ConstitutiveLawSelector & self,
+ const std::shared_ptr<ConstitutiveLawSelector> &
+ fallback_selector) { self.setFallback(fallback_selector); })
+ .def("__call__", &ConstitutiveLawSelector::operator());
+#if defined(AKANTU_SOLID_MECHANICS)
register_material_selectors<DefaultMaterialSelector>(
mod, "DefaultMaterialSelector")
- .def(py::init<const ElementTypeMapArray<Int> &>());
+ .def(py::init<const ElementTypeMapArray<Idx> &>());
register_material_selectors<MeshDataMaterialSelector<std::string>>(
mod, "MeshDataMaterialSelectorString")
- .def(py::init<const std::string &, const SolidMechanicsModel &, UInt>(),
+ .def(py::init<const std::string &, const SolidMechanicsModel &, Int>(),
py::arg("name"), py::arg("model"), py::arg("first_index") = 1);
+#endif
#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_material_selector.hh b/python/py_constitutive_law_selector.hh
similarity index 85%
rename from python/py_material_selector.hh
rename to python/py_constitutive_law_selector.hh
index dcc9e512f..830e7e184 100644
--- a/python/py_material_selector.hh
+++ b/python/py_constitutive_law_selector.hh
@@ -1,32 +1,32 @@
/**
* Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pybind11/pybind11.h>
-#ifndef AKANTU_PY_MATERIAL_SELECTOR_HH_
-#define AKANTU_PY_MATERIAL_SELECTOR_HH_
+#ifndef AKANTU_PY_CONSTITUTIVE_LAW_SELECTOR_HH_
+#define AKANTU_PY_CONSTITUTIVE_LAW_SELECTOR_HH_
namespace akantu {
-void register_material_selector(pybind11::module & mod);
+void register_constitutive_law_selector(pybind11::module & mod);
} // namespace akantu
#endif // AKANTU_PY_MATERIAL_SELECTOR_HH_
diff --git a/python/py_constitutive_laws_handler.hh b/python/py_constitutive_laws_handler.hh
new file mode 100644
index 000000000..5d407bc59
--- /dev/null
+++ b/python/py_constitutive_laws_handler.hh
@@ -0,0 +1,105 @@
+/* -------------------------------------------------------------------------- */
+#include <constitutive_laws_handler.hh>
+/* -------------------------------------------------------------------------- */
+#include <pybind11/pybind11.h>
+#include <pybind11/stl.h>
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_PY_CONSTITUTIVE_LAWS_HANDLER_HH_
+#define AKANTU_PY_CONSTITUTIVE_LAWS_HANDLER_HH_
+
+namespace akantu {
+
+template <class ConstitutiveLawType, class Model_>
+void register_constitutive_laws_handler(pybind11::module & mod) {
+ namespace py = pybind11;
+ using CLH = ConstitutiveLawsHandler<ConstitutiveLawType, Model_>;
+ std::string name = "ConstitutiveLawsHandler" +
+ debug::demangle<ConstitutiveLawType>() +
+ debug::demangle<Model_>();
+
+ py::class_<CLH, Model_>(mod, name.c_str(), py::multiple_inheritance())
+ .def(py::init<Mesh &, ModelType &, Int, const ID &>())
+ .def(
+ "registerNewConstitutiveLaw",
+ [](CLH & self, const ID & name, const ID & type,
+ const ID & opt_param) -> decltype(auto) {
+ return self.registerNewConstitutiveLaw(name, type, opt_param);
+ },
+ py::arg("name"), py::arg("type"), py::arg("opt_param") = "",
+ py::return_value_policy::reference)
+ .def("reassignConstitutiveLaw", &CLH::reassignConstitutiveLaw)
+ .def("isInternal", &CLH::isInternal, py::arg("field_name"),
+ py::arg("element_kind") = _ek_regular)
+ .def(
+ "flattenInternalReal",
+ [](CLH & self, const std::string & field_name, ElementKind kind,
+ GhostType ghost_type) -> decltype(auto) {
+ return self.template flattenInternal<Real>(field_name, kind,
+ ghost_type);
+ },
+ py::arg("field_name"), py::arg("kind") = _ek_regular,
+ py::arg("ghost_type") = _not_ghost,
+ py::return_value_policy::reference)
+ .def(
+ "inflateInternalReal",
+ [](CLH & self, const std::string & field_name,
+ const std::shared_ptr<ElementTypeMapArray<Real>> & field,
+ ElementKind kind, GhostType ghost_type) {
+ return self.template inflateInternal<Real>(field_name, *field,
+ ghost_type, kind);
+ },
+ py::arg("field_name"), py::arg("field"),
+ py::arg("kind") = _ek_regular, py::arg("ghost_type") = _not_ghost)
+ .def(
+ "getConstitutiveLaws",
+ [](CLH & self) -> decltype(auto) {
+ return self.getConstitutiveLaws();
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLaw",
+ [](CLH & self, Idx cl_index) -> decltype(auto) {
+ return self.getConstitutiveLaw(cl_index);
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLaw",
+ [](CLH & self, const std::string & name) -> decltype(auto) {
+ return self.getConstitutiveLaw(name);
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLaw",
+ [](CLH & self, const Element & element) -> decltype(auto) {
+ return self.getConstitutiveLaw(element);
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLawIndex",
+ [](CLH & self, const std::string & name) -> decltype(auto) {
+ return self.getConstitutiveLawIndex(name);
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getNbConstitutiveLaws",
+ [](CLH & self) -> decltype(auto) {
+ return self.getNbConstitutiveLaws();
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLawByElement",
+ [](const CLH & self) -> decltype(auto) {
+ return self.getConstitutiveLawByElement();
+ },
+ py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLawLocalNumbering",
+ [](const CLH & self) -> decltype(auto) {
+ return self.getConstitutiveLawLocalNumbering();
+ },
+ py::return_value_policy::reference);
+}
+} // namespace akantu
+
+#endif /* AKANTU_PY_CONSTITUTIVE_LAWS_HANDLER_HH_ */
diff --git a/python/py_contact_mechanics_model.hh b/python/py_contact_mechanics_model.hh
index 259ec4a53..b7b7c524b 100644
--- a/python/py_contact_mechanics_model.hh
+++ b/python/py_contact_mechanics_model.hh
@@ -1,30 +1,30 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pybind11/pybind11.h>
-#ifndef __AKANTU_PY_CONTACT_MECHANICS_MODEL_HH__
-#define __AKANTU_PY_CONTACT_MECHANICS_MODEL_HH__
+#ifndef AKANTU_PY_CONTACT_MECHANICS_MODEL_HH_
+#define AKANTU_PY_CONTACT_MECHANICS_MODEL_HH_
namespace akantu {
void register_contact_mechanics_model(pybind11::module & mod);
} // namespace akantu
-#endif // __AKANTU_PY_CONTACT_MECHANICS_MODEL_HH__
+#endif // AKANTU_PY_CONTACT_MECHANICS_MODEL_HH_
diff --git a/python/py_fe_engine.cc b/python/py_fe_engine.cc
index b0c6f03d0..4de1f9f0c 100644
--- a/python/py_fe_engine.cc
+++ b/python/py_fe_engine.cc
@@ -1,138 +1,139 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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>
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
void register_fe_engine(py::module & mod) {
py::class_<Element>(mod, "Element")
.def(py::init([](ElementType type, Int id, GhostType ghost_type) {
return std::make_unique<Element>(Element{type, id, ghost_type});
}),
py::arg("type"), py::arg("ghost_type"),
py::arg("ghost_type") = _not_ghost)
.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, ElementType type, GhostType ghost_type) {
return fem.getNbIntegrationPoints(type, ghost_type);
},
py::arg("type"), py::arg("ghost_type") = _not_ghost)
.def("initShapeFunctions", &FEEngine::initShapeFunctions,
py::arg("ghost_type") = _not_ghost)
.def(
"gradientOnIntegrationPoints",
[](FEEngine & fem, const Array<Real> & u, Array<Real> & nablauq,
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);
},
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") = empty_filter)
.def(
"interpolateOnIntegrationPoints",
[](FEEngine & self, const Array<Real> & u, Array<Real> & uq,
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") = empty_filter)
.def(
"interpolateOnIntegrationPoints",
[](FEEngine & self, const Array<Real> & u,
- ElementTypeMapArray<Real> & uq,
- const ElementTypeMapArray<Idx> * filter_elements) {
- self.interpolateOnIntegrationPoints(u, uq, filter_elements);
+ std::shared_ptr<ElementTypeMapArray<Real>> uq,
+ std::shared_ptr<const ElementTypeMapArray<Idx>> filter_elements) {
+ self.interpolateOnIntegrationPoints(u, *uq, filter_elements.get());
},
py::arg("u"), py::arg("uq"), py::arg("filter_elements") = nullptr)
.def(
"computeIntegrationPointsCoordinates",
- [](FEEngine & self, ElementTypeMapArray<Real> & coordinates,
- const ElementTypeMapArray<Idx> * filter_elements)
+ [](FEEngine & self,
+ std::shared_ptr<ElementTypeMapArray<Real>> coordinates,
+ std::shared_ptr<const ElementTypeMapArray<Idx>> filter_elements)
-> decltype(auto) {
- return self.computeIntegrationPointsCoordinates(coordinates,
- filter_elements);
+ return self.computeIntegrationPointsCoordinates(
+ *coordinates, filter_elements.get());
},
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_heat_transfer_model.cc b/python/py_heat_transfer_model.cc
index 859086a62..ee9e0df4e 100644
--- a/python/py_heat_transfer_model.cc
+++ b/python/py_heat_transfer_model.cc
@@ -1,88 +1,117 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_constitutive_law.hh"
+#include "py_constitutive_laws_handler.hh"
/* -------------------------------------------------------------------------- */
+#include <diffusion_law.hh>
+#include <diffusion_model.hh>
+#include <heat_diffusion.hh>
#include <heat_transfer_model.hh>
+#include <model_options.hh>
#include <non_linear_solver.hh>
/* -------------------------------------------------------------------------- */
-//#include <pybind11/operators.h>
+// #include <pybind11/operators.h>
#include <pybind11/pybind11.h>
-//#include <pybind11/stl.h>
+// #include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
-/* -------------------------------------------------------------------------- */
-#define def_function_nocopy(func_name) \
- def( \
- #func_name, \
- [](HeatTransferModel & self) -> decltype(auto) { \
- return self.func_name(); \
- }, \
- py::return_value_policy::reference)
+namespace {
+ template <typename _DiffusionLaw>
+ class PyDiffusionLaw : public _DiffusionLaw {
+ public:
+ /* Inherit the constructors */
+ using _DiffusionLaw::_DiffusionLaw;
-#define def_function(func_name) \
- def(#func_name, [](HeatTransferModel & self) -> decltype(auto) { \
- return self.func_name(); \
- })
-/* -------------------------------------------------------------------------- */
+ void computeDiffusivityGradUOnQuadPoints(ElementType type,
+ GhostType ghost_type) override {
+ PYBIND11_OVERRIDE(void, _DiffusionLaw,
+ computeDiffusivityGradUOnQuadPoints, type, ghost_type);
+ }
+
+ void computeDiffusivityOnQuadPoints(ElementType type,
+ GhostType ghost_type) override {
+ PYBIND11_OVERRIDE(void, _DiffusionLaw, computeDiffusivityOnQuadPoints,
+ type, ghost_type);
+ }
+
+ Real getStableTimeStep(Real element_size) override {
+ PYBIND11_OVERRIDE(Real, _DiffusionLaw, getStableTimeStep, element_size);
+ }
+ };
+ /* ------------------------------------------------------------------------ */
+ template <typename _DiffusionLaw>
+ void register_diffusion_law_classes(py::module & mod, const ID & name) {
+ py::class_<_DiffusionLaw, DiffusionLaw, PyDiffusionLaw<_DiffusionLaw>>(
+ mod, name.c_str(), py::multiple_inheritance())
+ .def(py::init<DiffusionModel &, const ID &>());
+ }
+} // namespace
+/* -------------------------------------------------------------------------- */
void register_heat_transfer_model(py::module & mod) {
- py::class_<HeatTransferModelOptions>(mod, "HeatTransferModelOptions")
- .def(py::init<AnalysisMethod>(),
- py::arg("analysis_method") = _explicit_lumped_mass);
+ register_constitutive_law<DiffusionModel>(mod);
- py::class_<HeatTransferModel, Model>(mod, "HeatTransferModel",
- py::multiple_inheritance())
- .def(py::init<Mesh &, UInt, const ID &>(), py::arg("mesh"),
- py::arg("spatial_dimension") = _all_dimensions,
- py::arg("id") = "heat_transfer_model")
- .def(
- "initFull",
- [](HeatTransferModel & self,
- const HeatTransferModelOptions & options) {
- self.initFull(options);
- },
- py::arg("_analysis_method") = HeatTransferModelOptions())
+ /* ------------------------------------------------------------------------ */
+ py::class_<DiffusionLaw, ConstitutiveLaw<DiffusionModel>>(
+ mod, "DiffusionLaw", py::multiple_inheritance());
+
+ register_diffusion_law_classes<HeatDiffusion<1>>(mod, "HeatDiffusion1D");
+ register_diffusion_law_classes<HeatDiffusion<2>>(mod, "HeatDiffusion2D");
+ register_diffusion_law_classes<HeatDiffusion<3>>(mod, "HeatDiffusion3D");
+
+ /* ------------------------------------------------------------------------ */
+ register_constitutive_laws_handler<DiffusionLaw, Model>(mod);
+
+ /* ------------------------------------------------------------------------ */
+ py::class_<DiffusionModel, ConstitutiveLawsHandler<DiffusionLaw, Model>>(
+ mod, "DiffusionModel", py::multiple_inheritance())
.def(
"initFull",
- [](HeatTransferModel & self,
- const AnalysisMethod & _analysis_method) {
+ [](DiffusionModel & self, const AnalysisMethod & _analysis_method) {
self.initFull(HeatTransferModelOptions(_analysis_method));
},
py::arg("_analysis_method"))
- .def("setTimeStep", &HeatTransferModel::setTimeStep, py::arg("time_step"),
+ .def("setTimeStep", &DiffusionModel::setTimeStep, py::arg("time_step"),
py::arg("solver_id") = "")
- .def_function(getStableTimeStep)
- .def_function_nocopy(getTemperature)
- .def_function_nocopy(getBlockedDOFs)
- .def("getTemperatureGradient", &HeatTransferModel::getTemperatureGradient,
- py::arg("el_type"), py::arg("ghost_type") = _not_ghost,
- py::return_value_policy::reference)
- .def("getKgradT", &HeatTransferModel::getKgradT, py::arg("el_type"),
- py::arg("ghost_type") = _not_ghost,
- py::return_value_policy::reference);
+ .def("getStableTimeStep", &DiffusionModel::getStableTimeStep)
+ .def("getBlockedDOFs", &DiffusionModel::getBlockedDOFs);
+
+ /* ------------------------------------------------------------------------ */
+ py::class_<HeatTransferModel, DiffusionModel>(mod, "HeatTransferModel",
+ py::multiple_inheritance())
+ .def(py::init<Mesh &, Int, const ID &>(), py::arg("mesh"),
+ py::arg("spatial_dimension") = _all_dimensions,
+ py::arg("id") = "diffusion_model")
+ .def(
+ "getTemperature",
+ [](HeatTransferModel & self) -> decltype(auto) {
+ return self.getTemperature();
+ },
+ py::return_value_policy::reference);
}
} // namespace akantu
diff --git a/python/py_material.cc b/python/py_material.cc
index 4376a2c13..2b56be2d4 100644
--- a/python/py_material.cc
+++ b/python/py_material.cc
@@ -1,404 +1,254 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "py_constitutive_law.hh"
/* -------------------------------------------------------------------------- */
+#include <constitutive_law.hh>
#include <material_selector.hh>
#include <solid_mechanics_model.hh>
#if defined(AKANTU_COHESIVE_ELEMENT)
#include <material_cohesive_linear.hh>
#include <material_cohesive_linear_friction.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);
+ PYBIND11_OVERRIDE(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 {
+ [[nodiscard]] Real
+ getPushWaveSpeed(const Element & element) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(Real, _Material, getPushWaveSpeed, element);
}
- Real getShearWaveSpeed(const Element & element) const override {
+ [[nodiscard]] Real
+ getShearWaveSpeed(const Element & element) const override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(Real, _Material, getShearWaveSpeed, element);
}
-
- template <typename T>
- 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>>(
+ py::class_<_Material, Material, PyMaterial<_Material>>(
mod, name.c_str(), py::multiple_inheritance())
- .def(py::init<SolidMechanicsModel &, const ID &>())
- .def("registerInternalReal",
- [](Material & self, const std::string & name, Int nb_component) {
- return dynamic_cast<PyMaterial<_Material> &>(self)
- .template registerInternal<Real>(name, nb_component);
- })
- .def("registerInternalUInt",
- [](Material & self, const std::string & name, Int nb_component) {
- return dynamic_cast<PyMaterial<_Material> &>(self)
- .template registerInternal<UInt>(name, nb_component);
- });
+ .def(py::init<SolidMechanicsModel &, const ID &>());
}
#if defined(AKANTU_COHESIVE_ELEMENT)
// trampoline for the cohesive materials
- template <typename _Material>
+ template <typename _Material,
+ std::enable_if_t<std::is_base_of_v<MaterialCohesive, _Material>> * =
+ nullptr>
class PyMaterialCohesive : public PyMaterial<_Material> {
- using Parent = PyMaterial<_Material>;
-
public:
+ using Parent = PyMaterial<_Material>;
+ /* Inherit the constructors */
using Parent::Parent;
void checkInsertion(bool check_only) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, checkInsertion, check_only);
}
void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override {
// NOLINTNEXTLINE
- PYBIND11_OVERRIDE_PURE(void, _Material, computeTraction, el_type,
- ghost_type);
+ PYBIND11_OVERRIDE(void, _Material, computeTraction, el_type, ghost_type);
}
void computeTangentTraction(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type = _not_ghost) override {
// NOLINTNEXTLINE
PYBIND11_OVERRIDE(void, _Material, computeTangentTraction, el_type,
tangent_matrix, ghost_type);
}
void computeStress(ElementType /*el_type*/,
GhostType /*ghost_type*/ = _not_ghost) final {}
void computeTangentModuli(ElementType /*el_type*/,
Array<Real> & /*tangent_matrix*/,
GhostType /*ghost_type*/ = _not_ghost) final {}
-
- template <typename T>
- 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;
- }
- };
-
- // trampoline for the cohesive material inheritance where computeTraction is
- // not pure virtual
- template <typename _Material>
- class PyMaterialCohesiveDaughters : public PyMaterialCohesive<_Material> {
- using Parent = PyMaterialCohesive<_Material>;
-
- public:
- using Parent::Parent;
-
- void computeTraction(ElementType el_type,
- GhostType ghost_type = _not_ghost) override {
- // NOLINTNEXTLINE
- PYBIND11_OVERRIDE(void, _Material, computeTraction, el_type, ghost_type);
- }
};
template <typename _Material>
void register_material_cohesive_classes(py::module & mod,
const std::string & name) {
- py::class_<_Material, MaterialCohesive,
- PyMaterialCohesiveDaughters<_Material>>(
+ py::class_<_Material, MaterialCohesive, PyMaterialCohesive<_Material>>(
mod, name.c_str(), py::multiple_inheritance())
- .def(py::init<SolidMechanicsModelCohesive &, const ID &>())
- .def("registerInternalReal",
- [](MaterialCohesive & self, const std::string & name,
- UInt nb_component) {
- auto & ref = dynamic_cast<PyMaterialCohesive<_Material> &>(self);
- return ref.template registerInternal<Real>(name, nb_component);
- })
- .def("registerInternalUInt",
- [](MaterialCohesive & self, const std::string & name,
- UInt nb_component) {
- return dynamic_cast<PyMaterialCohesive<_Material> &>(self)
- .template registerInternal<UInt>(name, nb_component);
- });
+ .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](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);
+ register_constitutive_law<SolidMechanicsModel>(mod);
- 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())
+ py::class_<Material, PyMaterial<Material>,
+ ConstitutiveLaw<SolidMechanicsModel>>(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, Element element) -> Real {
return self.getPotentialEnergy(element);
},
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, Int nb_component) {
- return dynamic_cast<PyMaterial<Material> &>(self)
- .registerInternal<Real>(name, nb_component);
- })
- .def("registerInternalUInt",
- [](Material & self, const std::string & name, Int nb_component) {
- return dynamic_cast<PyMaterial<Material> &>(self)
- .registerInternal<UInt>(name, nb_component);
+ .def("getModel",
+ [](Material & self) -> SolidMechanicsModel & {
+ return self.getModel();
})
- .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();
- });
+ .def("getShearWaveSpeed", &Material::getShearWaveSpeed);
- register_material_classes<MaterialElastic<2>>(mod, "MaterialElastic2D");
- register_material_classes<MaterialElastic<3>>(mod, "MaterialElastic3D");
+ register_material_classes<MaterialElastic<1>>(mod, "MaterialLinearElastic1D");
+ register_material_classes<MaterialElastic<2>>(mod, "MaterialLinearElastic2D");
+ register_material_classes<MaterialElastic<3>>(mod, "MaterialLinearElastic3D");
#if defined(AKANTU_COHESIVE_ELEMENT)
/* ------------------------------------------------------------------------ */
py::class_<MaterialCohesive, Material, PyMaterialCohesive<MaterialCohesive>>(
mod, "MaterialCohesive", py::multiple_inheritance())
.def(py::init<SolidMechanicsModelCohesive &, const ID &>())
- .def("registerInternalReal",
- [](MaterialCohesive & self, const std::string & name,
- UInt nb_component) {
- auto & ref =
- dynamic_cast<PyMaterialCohesive<MaterialCohesive> &>(self);
- return ref.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");
register_material_cohesive_classes<MaterialCohesiveLinearFriction<2>>(
mod, "MaterialCohesiveLinearFriction2D");
register_material_cohesive_classes<MaterialCohesiveLinearFriction<3>>(
mod, "MaterialCohesiveLinearFriction3D");
#endif
+
+ 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](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);
}
} // namespace akantu
diff --git a/python/py_mesh.cc b/python/py_mesh.cc
index 3104067e6..f44b808ee 100644
--- a/python/py_mesh.cc
+++ b/python/py_mesh.cc
@@ -1,276 +1,294 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <element_type_map.hh>
#include <fe_engine.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>
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, Int _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::kw_only(), 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)
- .def(
- "initialize",
- [](ElementTypeMapArray<T> & self, const FEEngine & fe_engine,
- 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(
- fe_engine, _ghost_type = ghost_type,
- _nb_component = nb_component,
- _spatial_dimension =
- (spatial_dimension == -2
- ? fe_engine.getMesh().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::kw_only(), 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;
+ 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, Int _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::kw_only(), 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)
+ .def(
+ "initialize",
+ [](ElementTypeMapArray<T> & self, const FEEngine & fe_engine,
+ 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(
+ fe_engine, _ghost_type = ghost_type,
+ _nb_component = nb_component,
+ _spatial_dimension =
+ (spatial_dimension == -2
+ ? fe_engine.getMesh().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::kw_only(), 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)
+ .def(
+ "initialize",
+ [](ElementTypeMapArray<T> & self, const FEEngine & fe_engine,
+ 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(
+ fe_engine, _ghost_type = ghost_type,
+ _nb_component = nb_component,
+ _spatial_dimension =
+ (spatial_dimension == -2
+ ? fe_engine.getMesh().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("fe_engine"), 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)
+ .def("getID", &ElementTypeMapArray<T>::getID);
}
} // 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<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 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 Int spatial_dimension, GhostType ghost_type,
ElementKind kind) {
return self.getNbElement(spatial_dimension, ghost_type, kind);
},
py::kw_only(), 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::kw_only(), 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("getUpperBounds", &Mesh::getUpperBounds)
.def("getLowerBounds", &Mesh::getLowerBounds)
.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, 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, 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_model.cc b/python/py_model.cc
index a09e8f9ba..21c9a7544 100644
--- a/python/py_model.cc
+++ b/python/py_model.cc
@@ -1,134 +1,202 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <constitutive_laws_handler.hh>
#include <model.hh>
#include <non_linear_solver.hh>
#include <solver_callback.hh>
#include <sparse_matrix_aij.hh>
#include <time_step_solver.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/operators.h>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
+template <class ConstitutiveLawType, class ModelType>
+void register_constitutive_law_handler(py::module & mod,
+ const std::string & name) {
+ py::class_<ConstitutiveLawsHandler<ConstitutiveLawType, ModelType>,
+ ModelType>(mod, name.c_str(), py::multiple_inheritance())
+ .def(
+ "getConstitutiveLaw",
+ [](ConstitutiveLawsHandler<ConstitutiveLawType, ModelType> & self,
+ UInt constitutive_law_id) -> decltype(auto) {
+ return self.getConstitutiveLaw(constitutive_law_id);
+ },
+ py::arg("constitutive_law_id"), py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLaw",
+ [](ConstitutiveLawsHandler<ConstitutiveLawType, ModelType> & self,
+ const ID & constitutive_law_name) -> decltype(auto) {
+ return self.getConstitutiveLaw(constitutive_law_name);
+ },
+ py::arg("constitutive_law_name"), py::return_value_policy::reference)
+ .def(
+ "getConstitutiveLaw",
+ [](ConstitutiveLawsHandler<ConstitutiveLawType, ModelType> & self,
+ const Element & element) -> decltype(auto) {
+ return self.getConstitutiveLaw(element);
+ },
+ py::arg("element"), py::return_value_policy::reference)
+
+ .def("getNbConstitutiveLaws",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::getNbConstitutiveLaws)
+ .def("getConstitutiveLawIndex",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::getConstitutiveLawIndex)
+ .def("setConstitutiveLawSelector",
+ [](ConstitutiveLawsHandler<ConstitutiveLawType, ModelType> & self,
+ std::shared_ptr<ConstitutiveLawSelector>
+ constitutive_law_selector) {
+ self.setConstitutiveLawSelector(constitutive_law_selector);
+ })
+ .def("getConstitutiveLawSelector",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::getConstitutiveLawSelector)
+ .def(
+ "getConstitutiveLawByElement",
+ [](const ConstitutiveLawsHandler<ConstitutiveLawType, ModelType> &
+ self) -> decltype(auto) {
+ return self.getConstitutiveLawByElement();
+ },
+ py::return_value_policy::reference, py::keep_alive<0, 1>())
+ .def("reassignConstitutiveLaw",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::reassignConstitutiveLaw)
+ .def(
+ "registerNewConstitutiveLaw",
+ [](ConstitutiveLawsHandler<ConstitutiveLawType, ModelType> & self,
+ const ID & cl_name, const ID & cl_type,
+ const ID & opt_param) -> decltype(auto) {
+ return self.registerNewConstitutiveLaw(cl_name, cl_type, opt_param);
+ },
+ py::arg("constitutive_law_name"), py::arg("constitutive_law_type"),
+ py::arg("option") = "", py::return_value_policy::reference)
+ .def("initConstitutiveLaws",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::initConstitutiveLaws)
+ .def("flattenInternal",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::flattenInternal,
+ py::return_value_policy::reference)
+ .def("inflateInternal",
+ &ConstitutiveLawsHandler<ConstitutiveLawType,
+ ModelType>::inflateInternal,
+ py::return_value_policy::reference);
+}
+
/* -------------------------------------------------------------------------- */
void register_model(py::module & mod) {
py::class_<ModelSolver, SolverCallback, Parsable>(mod, "ModelSolver",
py::multiple_inheritance())
.def(
"getNonLinearSolver",
[](ModelSolver & self, const ID & solver_id) -> NonLinearSolver & {
return self.getNonLinearSolver(solver_id);
},
py::arg("solver_id") = "", py::return_value_policy::reference)
.def(
"getTimeStepSolver",
[](ModelSolver & self, const ID & solver_id) -> TimeStepSolver & {
return self.getTimeStepSolver(solver_id);
},
py::arg("solver_id") = "", py::return_value_policy::reference)
.def(
"solveStep",
[](ModelSolver & self, const ID & solver_id) {
self.solveStep(solver_id);
},
py::arg("solver_id") = "")
.def(
"solveStep",
[](ModelSolver & self, SolverCallback & callback,
const ID & solver_id) { self.solveStep(callback, solver_id); },
py::arg("callback"), py::arg("solver_id") = "");
py::class_<Model, ModelSolver>(mod, "Model", py::multiple_inheritance())
.def("setBaseName", &Model::setBaseName)
.def("setDirectory", &Model::setDirectory)
.def("getFEEngine", &Model::getFEEngine, py::arg("name") = "",
py::return_value_policy::reference)
.def("getFEEngineBoundary", &Model::getFEEngine, py::arg("name") = "",
py::return_value_policy::reference)
.def("addDumpFieldVector", &Model::addDumpFieldVector)
.def("addDumpField", &Model::addDumpField)
.def("setBaseNameToDumper", &Model::setBaseNameToDumper)
.def("addDumpFieldVectorToDumper", &Model::addDumpFieldVectorToDumper)
.def("addDumpFieldToDumper", &Model::addDumpFieldToDumper)
.def("dump", [](Model & self) { self.dump(); })
.def(
"dump", [](Model & self, UInt step) { self.dump(step); },
py::arg("step"))
.def(
"dump",
[](Model & self, Real time, UInt step) { self.dump(time, step); },
py::arg("time"), py::arg("step"))
.def(
"dump",
[](Model & self, const std::string & dumper) { self.dump(dumper); },
py::arg("dumper_name"))
.def(
"dump",
[](Model & self, const std::string & dumper, UInt step) {
self.dump(dumper, step);
},
py::arg("dumper_name"), py::arg("step"))
.def(
"dump",
[](Model & self, const std::string & dumper, Real time, UInt step) {
self.dump(dumper, time, step);
},
py::arg("dumper_name"), py::arg("time"), py::arg("step"))
.def("initNewSolver", &Model::initNewSolver)
.def(
"getNewSolver",
[](Model & self, const std::string id,
const TimeStepSolverType & time,
const NonLinearSolverType & type) {
self.getNewSolver(id, time, type);
},
py::return_value_policy::reference)
.def(
"setIntegrationScheme",
[](Model & self, const std::string id, const std::string primal,
const IntegrationSchemeType & scheme_type,
IntegrationScheme::SolutionType solution_type) {
self.setIntegrationScheme(id, primal, scheme_type, solution_type);
},
py::arg("id"), py::arg("primal"), py::arg("scheme_type"),
py::arg("solution_type") =
IntegrationScheme::SolutionType::_not_defined)
- // .def("setIntegrationScheme",
- // [](Model & self, const std::string id, const std::string primal,
- // std::unique_ptr<IntegrationScheme> & scheme,
- // IntegrationScheme::SolutionType solution_type) {
- // self.setIntegrationScheme(id, primal, scheme, solution_type);
- // })
-
.def("getDOFManager", &Model::getDOFManager,
py::return_value_policy::reference)
.def("assembleMatrix", &Model::assembleMatrix);
}
} // namespace akantu
diff --git a/python/py_model_couplers.cc b/python/py_model_couplers.cc
index 4fa039c7c..e0039aaee 100644
--- a/python/py_model_couplers.cc
+++ b/python/py_model_couplers.cc
@@ -1,109 +1,123 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <aka_error.hh>
#include <cohesive_contact_solvercallback.hh>
#include <coupler_solid_cohesive_contact.hh>
#include <coupler_solid_contact.hh>
+#include <element_synchronizer.hh>
+#include <node_synchronizer.hh>
#include <non_linear_solver.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
namespace {
template <class CouplerSolidContact_>
auto register_coupler_solid_contact(py::module & mod,
const std::string & name)
-> py::class_<CouplerSolidContact_, Model> {
return py::class_<CouplerSolidContact_, Model>(mod, name.c_str(),
py::multiple_inheritance())
.def(py::init<Mesh &, UInt, const ID &, std::shared_ptr<DOFManager>>(),
py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "coupler_solid_contact",
py::arg("dof_manager") = nullptr)
.def("applyBC",
[](CouplerSolidContact_ & self,
BC::Dirichlet::DirichletFunctor & func,
const std::string & element_group) {
self.applyBC(func, element_group);
})
.def("applyBC",
[](CouplerSolidContact_ & self, BC::Neumann::NeumannFunctor & func,
const std::string & element_group) {
self.applyBC(func, element_group);
})
-
- .def("setTimeStep", &CouplerSolidContact_::setTimeStep,
- py::arg("time_step"), py::arg("solver_id") = "")
.def("getContactMechanicsModel",
&CouplerSolidContact_::getContactMechanicsModel,
- py::return_value_policy::reference);
+ py::return_value_policy::reference)
+ .def("getDisplacement", &CouplerSolidContact_::getDisplacement,
+ py::return_value_policy::reference)
+ .def("getVelocity", &CouplerSolidContact_::getVelocity,
+ py::return_value_policy::reference)
+ .def("getAcceleration", &CouplerSolidContact_::getAcceleration,
+ py::return_value_policy::reference)
+ .def("getMass", &CouplerSolidContact_::getMass,
+ py::return_value_policy::reference)
+ .def("getContactForce", &CouplerSolidContact_::getContactForce,
+ py::return_value_policy::reference)
+ .def("getContactDetector", &CouplerSolidContact_::getContactDetector,
+ py::return_value_policy::reference)
+ .def("setTimeStep", &CouplerSolidContact_::setTimeStep,
+ py::arg("time_step"), py::arg("solver_id") = "")
+ .def("getStableTimeStep", &CouplerSolidContact_::getStableTimeStep);
}
} // namespace
/* -------------------------------------------------------------------------- */
void register_model_couplers(py::module & mod) {
register_coupler_solid_contact<CouplerSolidContact>(mod,
"CouplerSolidContact")
.def(
"getSolidMechanicsModel",
[](CouplerSolidContact & self) -> decltype(auto) {
return self.getSolidMechanicsModel();
},
py::return_value_policy::reference)
.def(
"initFull",
[](CouplerSolidContact & self,
const AnalysisMethod & analysis_method) {
self.initFull(_analysis_method = analysis_method);
},
py::arg("_analysis_method") = _explicit_lumped_mass);
register_coupler_solid_contact<CouplerSolidCohesiveContact>(
mod, "CouplerSolidCohesiveContact")
.def(
"initFull",
[](CouplerSolidCohesiveContact & 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",
[](CouplerSolidCohesiveContact & self) {
return self.checkCohesiveStress();
})
.def(
"getSolidMechanicsModelCohesive",
[](CouplerSolidCohesiveContact & self) -> decltype(auto) {
return self.getSolidMechanicsModelCohesive();
},
py::return_value_policy::reference);
}
} // namespace akantu
diff --git a/python/py_model_couplers.hh b/python/py_model_couplers.hh
index 95df887bd..a07fc1176 100644
--- a/python/py_model_couplers.hh
+++ b/python/py_model_couplers.hh
@@ -1,30 +1,30 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pybind11/pybind11.h>
-#ifndef __AKANTU_PY_MODEL_COUPLERS_HH__
-#define __AKANTU_PY_MODEL_COUPLERS_HH__
+#ifndef AKANTU_PY_MODEL_COUPLERS_HH_
+#define AKANTU_PY_MODEL_COUPLERS_HH_
namespace akantu {
void register_model_couplers(pybind11::module & mod);
} // namespace akantu
-#endif // __AKANTU_PY_MODEL_COUPLERS_HH__
+#endif // AKANTU_PY_MODEL_COUPLERS_HH_
diff --git a/python/py_phase_field_model.cc b/python/py_phase_field_model.cc
index 0a9955502..543dc3a61 100644
--- a/python/py_phase_field_model.cc
+++ b/python/py_phase_field_model.cc
@@ -1,143 +1,138 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_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(); \
})
/* -------------------------------------------------------------------------- */
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 &, Int, const ID &, std::shared_ptr<DOFManager>,
const ModelType>(),
py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "phase_field_model",
py::arg("dof_manager") = nullptr,
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("applyDirichletBC",
[](PhaseFieldModel & /*self*/) {
PyErr_WarnEx(
PyExc_DeprecationWarning,
"applyDirichletBC() is deprecated, use applyBC instead", 1);
})
.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("getEnergy", [](PhaseFieldModel & self) { return self.getEnergy(); })
+ .def(
+ "getEnergy",
+ [](PhaseFieldModel & self, const ID & energy_id) {
+ return self.getEnergy(energy_id);
+ },
+ py::arg("energy_id") = "dissipated")
.def(
"getEnergy",
[](PhaseFieldModel & self, const std::string & group_id) {
return self.getEnergy(group_id);
},
py::arg("group_id"))
.def_function(assembleStiffnessMatrix)
.def_function(assembleInternalForces)
.def_function_nocopy(getDamage)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getBlockedDOFs)
- .def_function_nocopy(getMesh)
- .def_function(savePreviousDamage)
- .def_function(savePreviousState)
.def(
"getPhaseField",
[](PhaseFieldModel & self, Idx phase_field_id) -> decltype(auto) {
- return self.getPhaseField(phase_field_id);
+ return self.getConstitutiveLaw(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);
+ .def("getPhaseFieldIndex", &PhaseFieldModel::getConstitutiveLawIndex)
+ .def("setPhaseFieldSelector",
+ &PhaseFieldModel::setConstitutiveLawSelector);
}
void register_phase_field_coupler(py::module & mod) {
py::class_<CouplerSolidPhaseField, Model>(mod, "CouplerSolidPhaseField")
.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_phase_field_model.hh b/python/py_phase_field_model.hh
index 2e6e8c02b..0b3e17225 100644
--- a/python/py_phase_field_model.hh
+++ b/python/py_phase_field_model.hh
@@ -1,31 +1,31 @@
/**
* Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
#include <pybind11/pybind11.h>
-#ifndef __AKANTU_PY_PHASE_FIELD_MODEL_HH__
-#define __AKANTU_PY_PHASE_FIELD_MODEL_HH__
+#ifndef AKANTU_PY_PHASE_FIELD_MODEL_HH_
+#define AKANTU_PY_PHASE_FIELD_MODEL_HH_
namespace akantu {
void register_phase_field_model(pybind11::module & mod);
void register_phase_field_coupler(pybind11::module & mod);
} // namespace akantu
-#endif // __AKANTU_PY_PHASE_FIELD_MODEL_HH__
+#endif // AKANTU_PY_PHASE_FIELD_MODEL_HH_
diff --git a/python/py_solid_mechanics_model.cc b/python/py_solid_mechanics_model.cc
index a7db4a599..af94dd7e3 100644
--- a/python/py_solid_mechanics_model.cc
+++ b/python/py_solid_mechanics_model.cc
@@ -1,175 +1,176 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_constitutive_laws_handler.hh"
/* -------------------------------------------------------------------------- */
+#include <constitutive_law.hh>
+#include <constitutive_laws_handler.hh>
+#include <material.hh>
#include <non_linear_solver.hh>
#include <solid_mechanics_model.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
#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(py::module & mod) {
+ register_constitutive_laws_handler<Material, Model>(mod);
py::class_<SolidMechanicsModelOptions>(mod, "SolidMechanicsModelOptions")
.def(py::init<AnalysisMethod>(),
py::arg("_analysis_method") = _explicit_lumped_mass);
- py::class_<SolidMechanicsModel, Model>(mod, "SolidMechanicsModel",
- py::multiple_inheritance())
- .def(py::init<Mesh &, UInt, const ID &, std::shared_ptr<DOFManager>,
+ py::class_<SolidMechanicsModel, ConstitutiveLawsHandler<Material, Model>>(
+ mod, "SolidMechanicsModel", py::multiple_inheritance())
+ .def(py::init<Mesh &, Int, const ID &, std::shared_ptr<DOFManager>,
const ModelType>(),
py::arg("mesh"), py::arg("spatial_dimension") = _all_dimensions,
py::arg("id") = "solid_mechanics_model",
py::arg("dof_manager") = nullptr,
py::arg("model_type") = ModelType::_solid_mechanics_model)
.def(
"initFull",
[](SolidMechanicsModel & self,
const SolidMechanicsModelOptions & options) {
self.initFull(options);
},
py::arg("option") = SolidMechanicsModelOptions())
.def(
"initFull",
[](SolidMechanicsModel & self,
const AnalysisMethod & analysis_method) {
self.initFull(_analysis_method = analysis_method);
},
py::arg("_analysis_method"))
.def("applyDirichletBC",
[](SolidMechanicsModel & /*self*/) {
PyErr_WarnEx(
PyExc_DeprecationWarning,
"applyDirichletBC() is deprecated, use applyBC instead", 1);
})
.def("applyBC",
[](SolidMechanicsModel & self,
BC::Dirichlet::DirichletFunctor & func,
const std::string & element_group) {
self.applyBC(func, element_group);
})
.def("applyBC",
[](SolidMechanicsModel & self, BC::Neumann::NeumannFunctor & func,
const std::string & element_group) {
self.applyBC(func, element_group);
})
.def("setTimeStep", &SolidMechanicsModel::setTimeStep,
py::arg("time_step"), py::arg("solver_id") = "")
.def(
"getEnergy",
[](SolidMechanicsModel & self, const std::string & energy_id) {
return self.getEnergy(energy_id);
},
py::arg("energy_id"))
.def(
"getEnergy",
[](SolidMechanicsModel & self, const std::string & energy_id,
const std::string & group_id) {
return self.getEnergy(energy_id, group_id);
},
py::arg("energy_id"), py::arg("group_id"))
.def_function(assembleStiffnessMatrix)
.def_function(assembleInternalForces)
.def_function(assembleMass)
.def_function(assembleMassLumped)
.def_function(getStableTimeStep)
.def_function_nocopy(getExternalForce)
.def_function_nocopy(getDisplacement)
.def_function_nocopy(getPreviousDisplacement)
.def_function_nocopy(getCurrentPosition)
.def_function_nocopy(getIncrement)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getMass)
.def_function_nocopy(getVelocity)
.def_function_nocopy(getAcceleration)
.def_function_nocopy(getInternalForce)
.def_function_nocopy(getBlockedDOFs)
.def_function_nocopy(getMesh)
.def(
"getMaterial",
[](SolidMechanicsModel & self, UInt material_id) -> decltype(auto) {
return self.getMaterial(material_id);
},
py::arg("material_id"), py::return_value_policy::reference)
.def(
"getMaterial",
[](SolidMechanicsModel & self, const ID & material_name)
-> decltype(auto) { return self.getMaterial(material_name); },
py::arg("material_name"), py::return_value_policy::reference)
.def(
"getMaterial",
[](SolidMechanicsModel & self, const Element & element)
-> decltype(auto) { return self.getMaterial(element); },
py::arg("element"), py::return_value_policy::reference)
.def("getNbMaterials", &SolidMechanicsModel::getNbMaterials)
.def("getMaterialIndex", &SolidMechanicsModel::getMaterialIndex)
.def("setMaterialSelector",
[](SolidMechanicsModel & self,
- std::shared_ptr<MaterialSelector> material_selector) {
+ std::shared_ptr<ConstitutiveLawSelector> material_selector) {
std::cout << (*material_selector)(ElementNull) << std::endl;
self.setMaterialSelector(material_selector);
})
.def("getMaterialSelector", &SolidMechanicsModel::getMaterialSelector)
.def(
"getMaterialByElement",
[](const SolidMechanicsModel & self) -> decltype(auto) {
return self.getMaterialByElement();
},
py::return_value_policy::reference, py::keep_alive<0, 1>())
.def("reassignMaterial", &SolidMechanicsModel::reassignMaterial)
.def(
"registerNewMaterial",
[](SolidMechanicsModel & self, const ID & mat_name,
const ID & mat_type, const ID & opt_param) -> decltype(auto) {
return self.registerNewMaterial(mat_name, mat_type, opt_param);
},
py::arg("material_name"), py::arg("material_type"),
- py::arg("option") = "", py::return_value_policy::reference)
- .def("initMaterials", &SolidMechanicsModel::initMaterials)
- .def("flattenInternal", &SolidMechanicsModel::flattenInternal,
- py::return_value_policy::reference)
- .def("inflateInternal", &SolidMechanicsModel::inflateInternal,
- py::return_value_policy::reference);
+ py::arg("option") = "", py::return_value_policy::reference);
+ // .def("initMaterials", &SolidMechanicsModel::initMaterials)
}
} // namespace akantu
diff --git a/python/py_solid_mechanics_model_cohesive.cc b/python/py_solid_mechanics_model_cohesive.cc
index d4edc2156..d4d8c8db9 100644
--- a/python/py_solid_mechanics_model_cohesive.cc
+++ b/python/py_solid_mechanics_model_cohesive.cc
@@ -1,118 +1,119 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_synchronizer.hh>
#include <non_linear_solver.hh>
#include <solid_mechanics_model_cohesive.hh>
/* -------------------------------------------------------------------------- */
#include <pybind11/pybind11.h>
/* -------------------------------------------------------------------------- */
namespace py = pybind11;
/* -------------------------------------------------------------------------- */
namespace akantu {
#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 &, 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/setup.cfg b/setup.cfg
index a8b477d16..17ae0a3fd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,15 +1,17 @@
[cmake_config]
AKANTU_COHESIVE_ELEMENT = TRUE
AKANTU_IMPLICIT = TRUE
+AKANTU_IMPLICIT_SOLVER = Eigen
AKANTU_PARALLEL = FALSE
AKANTU_STRUCTURAL_MECHANICS = TRUE
-AKANTU_HEAT_TRANSFER = TRUE
+AKANTU_DIFFUSION = TRUE
AKANTU_DAMAGE_NON_LOCAL = TRUE
AKANTU_PHASE_FIELD = TRUE
AKANTU_PYTHON_INTERFACE = TRUE
AKANTU_CONTACT_MECHANICS = TRUE
AKANTU_EXAMPLES = FALSE
AKANTU_TESTS = FALSE
CMAKE_JOB_POOL_COMPILE = compile
CMAKE_JOB_POOL_LINK = link
CMAKE_JOB_POOLS = 'compile=4;link=2'
+CMAKE_MACOSX_RPATH = FALSE
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5dd68a051..c999c167f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,246 +1,258 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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()
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)
-
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_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")
+ if(_u_build_type MATCHES "DEBUG" OR _u_build_type MATCHES "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})
if(AKANTU_LIBRARY_PROPERTIES)
set_target_properties(akantu
PROPERTIES ${AKANTU_LIBRARY_PROPERTIES} # this contains the version
)
endif()
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(AKANTU_COMPILER_LAUNCHER)
+ set_property(TARGET akantu PROPERTY CXX_COMPILER_LAUNCHER "${AKANTU_COMPILER_LAUNCHER}")
+endif()
+
+set_property(TARGET akantu PROPERTY CXX_EXTENSIONS OFF)
+
target_compile_features(akantu PUBLIC cxx_std_${AKANTU_CXX_STANDARD})
set_target_properties(akantu
PROPERTIES CXX_STANDARD ${AKANTU_CXX_STANDARD})
if (AKANTU_COMPILER_LAUNCHER)
set_target_properties(akantu
PROPERTIES CXX_COMPILER_LAUNCHER ${AKANTU_COMPILER_LAUNCHER})
endif()
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()
+if(AKANTU_SPLIT_DWARF)
+ target_compile_options(akantu
+ PRIVATE $<$<CONFIG:DEBUG>:-gsplit-dwarf -gdwarf-5> $<$<CONFIG:SANITIZEDEBUG>:-gsplit-dwarf -gdwarf-5>
+ )
+ target_link_options(akantu
+ PRIVATE -fuse-ld=gold $<$<CONFIG:DEBUG>:-Wl,--gdb-index> $<$<CONFIG:SANITIZEDEBUG>:-Wl,--gdb-index>
+ )
+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)
+ string(TOUPPER "${CMAKE_BUILD_TYPE}" _u_build_type)
+ if(NOT _u_build_type MATCHES "DEBUG")
message(STATUS "IPO/LTO enabled")
set_property(TARGET akantu PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
+ else()
+ message(STATUS "IPO/LTO supported but deactivated in debug")
+ set_property(TARGET akantu PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
+ endif()
else()
message(STATUS "IPO/LTO not supported: <${ipo_error}>")
endif()
diff --git a/src/common/aka_bbox.hh b/src/common/aka_bbox.hh
index a76f92553..7cb514822 100644
--- a/src/common/aka_bbox.hh
+++ b/src/common/aka_bbox.hh
@@ -1,280 +1,281 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(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 {
+ template <class Derived>
+ inline bool contains(const Eigen::MatrixBase<Derived> & point) const {
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) {
+ /* ------------------------------------------------------------------------ */
+ template <class Derived>
+ inline void getCenter(Eigen::MatrixBase<Derived> & center) {
center = (upper_bounds + lower_bounds) / 2.;
}
/* ------------------------------------------------------------------------ */
const Vector<Real> & getLowerBounds() const { return lower_bounds; }
const Vector<Real> & getUpperBounds() const { 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);
reduce_bounds(0) = lower_bounds;
reduce_bounds(1) = Real(-1.) * upper_bounds;
communicator.allReduce(reduce_bounds, SynchronizerOperation::_min);
BBox global(dim);
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.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.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<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<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:
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_common.hh b/src/common/aka_common.hh
index e7bc42ac7..4433dfc1b 100644
--- a/src/common/aka_common.hh
+++ b/src/common/aka_common.hh
@@ -1,700 +1,703 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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 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
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) \
- (smm_gradu) \
+ (smm_gradu) \
(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) \
+ (diffusion) \
+ (diffusion_gradient) \
(htm_phi) \
(htm_gradient_phi) \
(pfm_damage) \
(csp_damage) \
(csp_strain) \
(mnl_for_average) \
(mnl_weight) \
(nh_criterion) \
(test) \
(user_1) \
(user_2) \
- (material_id) \
- (phasefield_id) \
+ (constitutive_law_id) \
+ (clh_init_cl) \
(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
- _smm_gradu, ///< synchronization of the gradu to compute the
+ _smm_gradu, ///< synchronization of the gradu to compute the
///< strain
_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_damage, ///< synchronization of the nodal damage
+
// --- 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
- _phasefield_id, ///< synchronization of the phasefield ids
- _for_dump, ///< everything that needs to be synch before dump
+ _test, ///< Test tag
+ _user_1, ///< tag for user simulations
+ _user_2, ///< tag for user simulations
+ _constitutive_law_id, ///< synchronization of the material ids
+ _clh_init_cl, ///< synchronization of the data to initialize materials
+ _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 auto get##name() const->type { return variable; }
+ [[nodiscard]] inline auto get##name() const -> type { return variable; }
#define AKANTU_GET_MACRO_AUTO(name, variable) \
- inline decltype(auto) get##name() const { return (variable); }
+ [[nodiscard]] 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 auto get##name()->type { return variable; }
+ [[nodiscard]] inline auto get##name() -> type { return variable; }
#define AKANTU_GET_MACRO_DEREF_PTR(name, ptr) \
- inline const auto & get##name() const { \
+ [[nodiscard]] 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 decltype(auto) get##name() { \
+ [[nodiscard]] 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 auto get##name(const support & el_type, \
- GhostType ghost_type = _not_ghost) \
+ [[nodiscard]] 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 auto to_lower(const std::string & str) -> std::string;
+[[nodiscard]] inline auto to_lower(const std::string & str) -> std::string;
/* -------------------------------------------------------------------------- */
-inline auto trim(const std::string & to_trim) -> std::string;
-inline auto trim(const std::string & to_trim, char c) -> std::string;
+[[nodiscard]] inline auto trim(const std::string & to_trim) -> std::string;
+[[nodiscard]] 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> auto printMemorySize(UInt size) -> std::string;
/* -------------------------------------------------------------------------- */
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* Type traits */
/* -------------------------------------------------------------------------- */
namespace aka {
/* ------------------------------------------------------------------------ */
template <typename T> using is_scalar = std::is_arithmetic<T>;
/* ------------------------------------------------------------------------ */
template <typename R, typename T,
std::enable_if_t<std::is_reference_v<T>> * = nullptr>
-auto is_of_type(T && t) -> bool {
+[[nodiscard]] auto is_of_type(T && t)
+ -> bool { // NOLINT(cppcoreguidelines-missing-std-forward)
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 {
+[[nodiscard]] 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>
-decltype(auto) as_type(const std::shared_ptr<T> & t) {
+[[nodiscard]] 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_v<T>> * = nullptr>
-decltype(auto) as_type(T && t) {
+[[nodiscard]] decltype(auto)
+as_type(T && t) { // NOLINT(cppcoreguidelines-missing-std-forward)
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) {
+[[nodiscard]] decltype(auto)
+as_type(T && t) { // NOLINT(cppcoreguidelines-missing-std-forward)
return &as_type<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();
+[[nodiscard]] cppargparse::ArgumentParser & getStaticArgumentParser();
/// get access to the internal input file parser
-Parser & getStaticParser();
+[[nodiscard]] Parser & getStaticParser();
/// get access to the user part of the internal input file parser
-const ParserSection & getUserParser();
+[[nodiscard]] 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;
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.cc.in b/src/common/aka_config.cc.in
index 0ee47db13..84480ae31 100644
--- a/src/common/aka_config.cc.in
+++ b/src/common/aka_config.cc.in
@@ -1,11 +1,13 @@
/* -------------------------------------------------------------------------- */
#include "aka_config.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
-std::string getVersion() {
- return std::string(
- "@AKANTU_MAJOR_VERSION@.@AKANTU_MINOR_VERSION@.@AKANTU_PATCH_VERSION@"
- "@AKANTU_PRERELEASE_VERSION@@AKANTU_LOCAL_VERSION@");
+std::string_view getVersion() {
+ // clang-format off
+ constexpr std::string_view version = {
+ "@AKANTU_MAJOR_VERSION@.@AKANTU_MINOR_VERSION@.@AKANTU_PATCH_VERSION@@AKANTU_PRERELEASE_VERSION@@AKANTU_LOCAL_VERSION@"};
+ // clang-format on
+ return version;
}
} // namespace akantu
diff --git a/src/common/aka_config.hh.in b/src/common/aka_config.hh.in
index 081b6440c..9e1fda825 100644
--- a/src/common/aka_config.hh.in
+++ b/src/common/aka_config.hh.in
@@ -1,111 +1,111 @@
/**
* @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>
+#include <string_view>
/* -------------------------------------------------------------------------- */
#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();
+std::string_view 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_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_DIFFUSION
#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_element_classes_info.hh b/src/common/aka_element_classes_info.hh
index 5bb0153d9..1dc47eead 100644
--- a/src/common/aka_element_classes_info.hh
+++ b/src/common/aka_element_classes_info.hh
@@ -1,240 +1,240 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 \
+#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
deleted file mode 100644
index 8eb2018e8..000000000
--- a/src/common/aka_element_classes_info.hh.in
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- * @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 */
-/* -------------------------------------------------------------------------- */
-#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
-};
-
-
-@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_error.cc b/src/common/aka_error.cc
index 9a8478ff5..f13a69a14 100644
--- a/src/common/aka_error.cc
+++ b/src/common/aka_error.cc
@@ -1,355 +1,362 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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;
+ int status{};
std::string result;
- char * demangled_name;
+ char * demangled_name{nullptr};
if ((demangled_name = abi::__cxa_demangle(symbol, nullptr, nullptr,
&status)) != nullptr) {
result = demangled_name;
- free(demangled_name);
+ std::free(demangled_name); // NOLINT
} else {
result = symbol;
}
return result;
}
/* ------------------------------------------------------------------------ */
+// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays,
+// cppcoreguidelines-pro-bounds-pointer-arithmetic,
+// performance-inefficient-string-concatenation,
+// cppcoreguidelines-owning-memory)
#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;
+ 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;
+ size_t stack_depth{};
void * stack_addrs[max_depth];
- char ** stack_strings;
+ char ** stack_strings{nullptr};
- size_t i;
+ size_t i{};
stack_depth = backtrace(stack_addrs, max_depth);
- stack_strings = backtrace_symbols(stack_addrs, stack_depth);
+ stack_strings = backtrace_symbols(stack_addrs, int(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;
+ 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;
+ 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;
}
+ // NOLINTEND(cppcoreguidelines-avoid-c-arrays,
+ // cppcoreguidelines-pro-bounds-pointer-arithmetic,
+ // performance-inefficient-string-concatenation,
+ // cppcoreguidelines-owning-memory)
/* ------------------------------------------------------------------------ */
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::cerr << " [" << std::setw(int(w)) << (std::get<0>(data) + 1) << "] "
<< std::get<1>(data) << "\n";
}
- std::cerr << "END BACKTRACE" << std::endl;
+ std::cerr << "END BACKTRACE"
+ << "\n";
}
/* ------------------------------------------------------------------------ */
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;
+ << "\n";
}
} catch (Exception & e) {
printBacktrace(e.backtrace());
std::cerr << "!! Uncaught akantu::Exception of type " << name
- << " !!\nwhat(): \"" << e.what() << "\"" << std::endl;
+ << " !!\nwhat(): \"" << e.what() << "\""
+ << "\n";
} catch (std::exception & e) {
std::cerr << "!! Uncaught exception of type " << name
- << " !!\nwhat(): \"" << e.what() << "\"" << std::endl;
+ << " !!\nwhat(): \"" << e.what() << "\""
+ << "\n";
} catch (...) {
std::cerr << "!! Something strange of type \"" << name
- << "\" was thrown.... !!" << std::endl;
+ << "\" was thrown.... !!"
+ << "\n";
}
if (debugger.printBacktrace()) {
std::cerr << "Random generator seed: " << RandomGenerator<Int>::seed()
- << std::endl;
+ << "\n";
printBacktrace();
}
}
} // namespace
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
- Debugger::Debugger() noexcept {
- cout = &std::cerr;
- level = dblWarning;
- parallel_context = "";
- file_open = false;
- print_backtrace = false;
-
+ Debugger::Debugger() noexcept : cout(&std::cerr) {
// 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 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;
+ << " " << info << "\n";
}
}
/* ------------------------------------------------------------------------ */
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;
}
+ // NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
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;
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 49730673f..59eb51f33 100644
--- a/src/common/aka_error.hh
+++ b/src/common/aka_error.hh
@@ -1,410 +1,429 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(); }
+ [[nodiscard]] const char * what() const noexcept override {
+ return _info.c_str();
+ }
- virtual std::string info() const noexcept {
+ [[nodiscard]] 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_; }
+ [[nodiscard]] 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;
+ [[nodiscard]] 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 {
+ [[nodiscard]] 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; }
+ [[nodiscard]] 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;
+ (*cout) << module_ << "\n";
}
}
private:
std::string parallel_context;
std::ostream * cout;
- bool file_open;
- DebugLevel level;
- bool print_backtrace;
+ bool file_open{false};
+ DebugLevel level{dblWarning};
+ bool print_backtrace{false};
std::set<std::string> modules_to_debug;
};
extern Debugger debugger; // NOLINT
+
+ struct DebugLevelContext {
+ DebugLevelContext(const DebugLevelContext &) = default;
+ DebugLevelContext(DebugLevelContext &&) = delete;
+ DebugLevelContext & operator=(const DebugLevelContext &) = default;
+ DebugLevelContext & operator=(DebugLevelContext &&) = delete;
+
+ DebugLevelContext(const DebugLevel & new_dbl) : save(getDebugLevel()) {
+ setDebugLevel(new_dbl);
+ }
+ ~DebugLevelContext() { setDebugLevel(save); }
+
+ private:
+ DebugLevel save;
+ };
+
} // 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 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_random_generator.hh b/src/common/aka_random_generator.hh
index fc4f6a40b..47e32f434 100644
--- a/src/common/aka_random_generator.hh
+++ b/src/common/aka_random_generator.hh
@@ -1,310 +1,317 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 */
/* -------------------------------------------------------------------------- */
#define AKANTU_RANDOM_DISTRIBUTION_TYPES \
(uniform)(exponential)( \
gamma)(weibull)(extreme_value)(normal)(lognormal)(chi_squared)(cauchy)(fisher_f)(student_t)(not_defined)
AKANTU_CLASS_ENUM_DECLARE(RandomDistributionType,
AKANTU_RANDOM_DISTRIBUTION_TYPES)
AKANTU_CLASS_ENUM_OUTPUT_STREAM(RandomDistributionType,
AKANTU_RANDOM_DISTRIBUTION_TYPES)
AKANTU_CLASS_ENUM_INPUT_STREAM(RandomDistributionType,
AKANTU_RANDOM_DISTRIBUTION_TYPES)
/* -------------------------------------------------------------------------- */
/* 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 << "]";
}
+
+
+ std::default_random_engine & getGenerator(); // Needed on apple clang
/* ------------------------------------------------------------------------ */
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
/* -------------------------------------------------------------------------- */
/* Some Helper */
/* -------------------------------------------------------------------------- */
template <typename T, class Distribution> struct RandomDistributionTypeHelper {
static constexpr RandomDistributionType value =
RandomDistributionType::_not_defined;
};
template <>
struct RandomDistributionTypeHelper<Real,
std::uniform_real_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_uniform;
};
template <>
struct RandomDistributionTypeHelper<Real, std::exponential_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_exponential;
};
template <>
struct RandomDistributionTypeHelper<Real, std::gamma_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_gamma;
};
template <>
struct RandomDistributionTypeHelper<Real, std::weibull_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_weibull;
};
template <>
struct RandomDistributionTypeHelper<Real,
std::extreme_value_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_extreme_value;
};
template <>
struct RandomDistributionTypeHelper<Real, std::normal_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_normal;
};
template <>
struct RandomDistributionTypeHelper<Real, std::lognormal_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_lognormal;
};
template <>
struct RandomDistributionTypeHelper<Real, std::chi_squared_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_chi_squared;
};
template <>
struct RandomDistributionTypeHelper<Real, std::cauchy_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_cauchy;
};
template <>
struct RandomDistributionTypeHelper<Real, std::fisher_f_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_fisher_f;
};
template <>
struct RandomDistributionTypeHelper<Real, std::student_t_distribution<Real>> {
static constexpr RandomDistributionType value =
RandomDistributionType::_student_t;
};
/* -------------------------------------------------------------------------- */
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<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<Idx> & gen) override {
- return distribution(gen);
+ return this->distribution(gen.getGenerator());
}
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 {
stream << std::to_string(
RandomDistributionTypeHelper<T, Distribution>::value);
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<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;
}
template <typename T>
auto make_random_parameter(
T base,
RandomDistributionType distribution = RandomDistributionType::_uniform,
T a = T(), T b = T()) {
switch (distribution) {
case RandomDistributionType::_not_defined:
return RandomParameter<T>(base, std::uniform_real_distribution<T>(0., 0.));
case RandomDistributionType::_uniform:
return RandomParameter<T>(base, std::uniform_real_distribution<T>(a, b));
case RandomDistributionType::_exponential:
return RandomParameter<T>(base, std::exponential_distribution<T>(a));
case RandomDistributionType::_gamma:
return RandomParameter<T>(base, std::gamma_distribution<T>(a, b));
case RandomDistributionType::_weibull:
return RandomParameter<T>(base, std::weibull_distribution<T>(b, a));
case RandomDistributionType::_extreme_value:
return RandomParameter<T>(base, std::extreme_value_distribution<T>(a, b));
case RandomDistributionType::_normal:
return RandomParameter<T>(base, std::normal_distribution<T>(a, b));
case RandomDistributionType::_lognormal:
return RandomParameter<T>(base, std::lognormal_distribution<T>(a, b));
case RandomDistributionType::_chi_squared:
return RandomParameter<T>(base, std::chi_squared_distribution<T>(a));
case RandomDistributionType::_cauchy:
return RandomParameter<T>(base, std::cauchy_distribution<T>(a, b));
case RandomDistributionType::_fisher_f:
return RandomParameter<T>(base, std::fisher_f_distribution<T>(a, b));
case RandomDistributionType::_student_t:
return RandomParameter<T>(base, std::student_t_distribution<T>(a));
}
return RandomParameter<T>(base, std::uniform_real_distribution<T>(0., 0.));
}
+
+
+ template<typename T>
+ std::default_random_engine & RandomGenerator<T>::getGenerator() { return generator; } // Needed on apple clang
} // namespace akantu
#endif /* AKANTU_AKA_RANDOM_GENERATOR_HH_ */
diff --git a/src/common/aka_types.hh b/src/common/aka_types.hh
index 08a0c206d..3a6414c94 100644
--- a/src/common/aka_types.hh
+++ b/src/common/aka_types.hh
@@ -1,538 +1,551 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_compatibilty_with_cpp_standard.hh"
#include "aka_error.hh"
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <array>
#include <initializer_list>
#include <numeric>
#include <type_traits>
#ifndef AKANTU_AKA_TYPES_HH
#define AKANTU_AKA_TYPES_HH
/* -------------------------------------------------------------------------- */
#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, ", ", ", ", \
"[", "]", "[", "]")
/* -------------------------------------------------------------------------- */
#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>
/* -------------------------------------------------------------------------- */
namespace aka {
template <typename T> struct is_eigen_map : public std::false_type {};
template <typename PlainObjectType, int MapOptions, typename StrideType>
struct is_eigen_map<Eigen::Map<PlainObjectType, MapOptions, StrideType>>
: public std::true_type {};
/* -------------------------------------------------------------------------- */
template <typename T> struct is_eigen_matrix : public std::false_type {};
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 T> struct is_eigen_matrix_base : public std::false_type {};
template <typename Derived>
struct is_eigen_matrix_base<Eigen::MatrixBase<Derived>>
: public std::true_type {};
} // namespace aka
namespace akantu {
using Eigen::Ref;
template <typename T, Eigen::Index n = Eigen::Dynamic>
using Vector = Eigen::Matrix<T, n, 1>;
template <typename T, Eigen::Index m = Eigen::Dynamic,
Eigen::Index n = Eigen::Dynamic>
using Matrix = Eigen::Matrix<T, m, 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>>>;
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>>>;
using VectorXr = Vector<Real>;
using MatrixXr = Matrix<Real>;
enum NormType : int8_t { L_1 = 1, L_2 = 2, L_inf = -1 };
struct TensorTraitBase {};
template <size_t n> struct TensorTrait : public TensorTraitBase {};
} // namespace akantu
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;
template <typename Derived> using is_matrix = aka::negation<is_vector<Derived>>;
template <class M> inline constexpr bool is_matrix_v = is_matrix<M>::value;
template <typename... Ds>
using are_vectors = aka::conjunction<is_vector<Ds>...>;
template <class... Vs>
inline constexpr bool are_vectors_v = are_vectors<Vs...>::value;
template <typename... Ds>
using are_matrices = aka::conjunction<is_matrix<Ds>...>;
template <class... Ms>
inline constexpr bool are_matrices_v = are_matrices<Ms...>::value;
template <typename... Ds>
using enable_if_matrices_t = std::enable_if_t<are_matrices<Ds...>::value>;
template <typename... Ds>
using enable_if_vectors_t = std::enable_if_t<are_vectors<Ds...>::value>;
/* -------------------------------------------------------------------------- */
template <typename T>
struct is_tensor : public std::is_base_of<akantu::TensorTraitBase, T> {};
template <typename PlainObjectType, int MapOptions, typename StrideType>
struct is_tensor<Eigen::Map<PlainObjectType, MapOptions, StrideType>>
: public std::true_type {};
template <typename XprType, int BlockRows, int BlockCols, bool InnerPanel>
struct is_tensor<Eigen::Block<XprType, BlockRows, BlockCols, InnerPanel>>
: public std::true_type {};
template <typename T, Eigen::Index m, Eigen::Index n>
struct is_tensor<Eigen::Matrix<T, m, n>> : public std::true_type {};
template <typename T, size_t n>
using is_tensor_n = std::is_base_of<akantu::TensorTrait<n>, T>;
template <class T> inline constexpr bool is_tensor_v = is_tensor<T>::value;
template <class T, size_t n>
inline constexpr bool is_tensor_n_v = is_tensor_n<T, n>::value;
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 <std::size_t n, typename T = void, typename... Ts>
using enable_if_tensors_n_t = typename enable_if_tensors_n<n, T, Ts...>::type;
} // namespace aka
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
/* -------------------------------------------------------------------------- */
#include "aka_view_iterators.hh"
/* -------------------------------------------------------------------------- */
-#include "aka_tensor.hh"
+#include "aka_tensor.hh" // NOLINT(unused-includes)
/* -------------------------------------------------------------------------- */
namespace akantu {
class ArrayBase;
/* -------------------------------------------------------------------------- */
namespace details {
- template <typename T> struct MapPlainObjectType { using type = T; };
+ template <typename T> struct MapPlainObjectType {
+ using type = T;
+ };
template <typename PlainObjectType, int MapOptions, typename StrideType>
struct MapPlainObjectType<
Eigen::Map<PlainObjectType, MapOptions, StrideType>> {
using type = PlainObjectType;
};
template <typename T>
using MapPlainObjectType_t = typename MapPlainObjectType<T>::type;
template <typename Scalar, Idx...> struct EigenMatrixViewHelper {};
template <typename Scalar, Idx RowsAtCompileTime>
struct EigenMatrixViewHelper<Scalar, RowsAtCompileTime> {
using type = Eigen::Matrix<Scalar, RowsAtCompileTime, 1>;
};
template <typename Scalar, Idx RowsAtCompileTime, Idx ColsAtCompileTime>
struct EigenMatrixViewHelper<Scalar, RowsAtCompileTime, ColsAtCompileTime> {
using type = Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime>;
};
template <typename Scalar, Idx... sizes>
using EigenMatrixViewHelper_t =
typename EigenMatrixViewHelper<Scalar, sizes...>::type;
template <typename Array, Idx... sizes> class EigenView {
static_assert(sizeof...(sizes) == 1 or sizeof...(sizes) == 2,
"Eigen only supports Vector and Matrices");
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();
}
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();
}
using ArrayRef_t = decltype(std::ref(std::declval<Array>()));
public:
using size_type = typename std::decay_t<Array>::size_type;
using value_type = typename std::decay_t<Array>::value_type;
- EigenView(Array && array, decltype(sizes)... sizes_)
+ EigenView(Array && array, decltype(sizes)... sizes_) // NOLINT
: array(std::ref(array)), sizes_(sizes_...) {}
- EigenView(Array && array) : array(array), sizes_(sizes...) {}
+ EigenView(Array && array) : array(std::ref(array)), sizes_(sizes...) {} // NOLINT
EigenView(const EigenView & other) = default;
EigenView(EigenView && other) noexcept = default;
+ ~EigenView() = default;
auto operator=(const EigenView & other) -> EigenView & = default;
auto operator=(EigenView && other) noexcept -> EigenView & = default;
template <typename A = Array, std::enable_if_t<not std::is_const_v<
std::remove_reference_t<A>>> * = 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_));
}
template <typename A = Array, std::enable_if_t<not std::is_const_v<
std::remove_reference_t<A>>> * = 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_));
}
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_));
}
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_));
}
private:
ArrayRef_t array;
std::tuple<decltype(sizes)...> sizes_;
};
} // namespace details
template <Idx RowsAtCompileTime, typename Array>
decltype(auto) make_view(Array && array, Idx rows = RowsAtCompileTime) {
return details::EigenView<Array, RowsAtCompileTime>(
std::forward<Array>(array), rows);
}
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);
}
template <Idx RowsAtCompileTime, typename Array>
decltype(auto) make_const_view(const Array & array,
Idx rows = RowsAtCompileTime) {
return make_view<RowsAtCompileTime>(array, rows);
}
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);
}
} // namespace akantu
namespace Eigen {
template <typename Derived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void MatrixBase<Derived>::zero() {
return this->fill(0.);
}
/* -------------------------------------------------------------------------- */
/* 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());
}
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());
}
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 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());
}
/* -------------------------------------------------------------------------- */
/* 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 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());
}
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());
+ const_cast<Scalar *>(this->derived().data()), this->rows()); // NOLINT
}
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(),
+ const_cast<Scalar *>(this->derived().data()) + this->size(), // NOLINT
this->rows());
}
+template <typename Derived>
+template <typename OtherScalar>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE auto MatrixBase<Derived>::eig() const {
+ EigenSolver<akantu::details::MapPlainObjectType_t<std::decay_t<Derived>>>
+ solver(*this, false);
+ if constexpr (std::is_floating_point<OtherScalar>{}) {
+ return solver.eigenvalues().real();
+ } else {
+ return solver.eigenvalues();
+ }
+}
+
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();
}
}
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);
// 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_);
auto norm = this->norm();
using OtherScalar = typename D1::Scalar;
if ((solver.eigenvectors().imag().template lpNorm<Infinity>() >
1e-15 * norm) and
std::is_floating_point<OtherScalar>::value) {
AKANTU_EXCEPTION("This matrix has complex eigenvectors()");
}
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;
}
if (not std::is_floating_point<OtherScalar>::value) {
AKANTU_EXCEPTION("Cannot sort complex eigen values");
}
values = solver.eigenvalues().real();
PermutationMatrix<Dynamic> P(values.size());
P.setIdentity();
- std::sort(P.indices().data(), P.indices().data() + P.indices().size(),
+ std::sort(P.indices().begin(), P.indices().end(),
[&values](const Index & a, const Index & b) {
return (values(a) - values(b)) > 0;
});
if constexpr (std::is_floating_point<OtherScalar>{}) {
values = P.transpose() * values;
vectors = solver.eigenvectors().real() * P;
}
- return;
}
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_);
+ auto & values = const_cast<MatrixBase<OtherDerived> &>(values_); // NOLINT
values = solver.eigenvalues();
}
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);
// 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_);
+ auto & values = const_cast<MatrixBase<D1> &>(values_); // NOLINT
+ auto & vectors = const_cast<MatrixBase<D2> &>(vectors_); // NOLINT
if (not sort) {
values = solver.eigenvalues();
vectors = solver.eigenvectors();
return;
}
values = solver.eigenvalues();
PermutationMatrix<Dynamic> P(values.size());
P.setIdentity();
- std::sort(P.indices().data(), P.indices().data() + P.indices().size(),
+ std::sort(P.indices().begin(), P.indices().end(),
[&values](const Index & a, const Index & b) {
return (values(a) - values(b)) > 0;
});
values = P.transpose() * values;
vectors = solver.eigenvectors() * P; // permutes the columns (eigen vectors)
}
} // namespace Eigen
namespace std {
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 */
diff --git a/src/common/aka_types_eigen_matrix_base_plugin.hh b/src/common/aka_types_eigen_matrix_base_plugin.hh
index 235bd439e..a0fe7d3cf 100644
--- a/src/common/aka_types_eigen_matrix_base_plugin.hh
+++ b/src/common/aka_types_eigen_matrix_base_plugin.hh
@@ -1,189 +1,192 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
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 OtherScalar>
+EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE auto eig() const;
+
template <typename OtherDerived>
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void
-eig(MatrixBase<OtherDerived> & other) const;
+eig(MatrixBase<OtherDerived> & values) 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;
+eigh(const MatrixBase<OtherDerived> & values_) const;
template <typename D1, typename D2>
-EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE void eigh(const MatrixBase<D1> & values,
- const MatrixBase<D2> & vectors,
+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_plain_object_base_plugin.hh b/src/common/aka_types_eigen_plain_object_base_plugin.hh
index 7a92c502b..b2fa662b8 100644
--- a/src/common/aka_types_eigen_plain_object_base_plugin.hh
+++ b/src/common/aka_types_eigen_plain_object_base_plugin.hh
@@ -1,75 +1,80 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
+// NOLINTBEGIN
#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());
+ if constexpr (Base::SizeAtCompileTime != 1) {
+ 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
+
+// NOLINTEND
diff --git a/src/common/aka_voigthelper.cc b/src/common/aka_voigthelper.cc
deleted file mode 100644
index 81b9e7c70..000000000
--- a/src/common/aka_voigthelper.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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 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 7e955ed44..36e455938 100644
--- a/src/common/aka_voigthelper.hh
+++ b/src/common/aka_voigthelper.hh
@@ -1,94 +1,129 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
+namespace details {
+ template <Int dim> struct VoigtHelperData {
+ static inline constexpr Int size{(dim * (dim - 1)) / 2 + dim};
+ // matrix of vector index I as function of tensor indices i,j
+ static constexpr std::array<std::array<Idx, dim>, dim> mat{};
+ // array of matrix indices ij as function of vector index I
+ static constexpr std::array<std::array<Idx, 2>, dim * dim> vec{};
+ // factors to multiply the strain by for voigt notation
+ static constexpr std::array<Real, size> factors{};
+ };
+
+ template <> struct VoigtHelperData<1> {
+ static constexpr Int size{1};
+ static constexpr std::array<std::array<Idx, 1>, 1> mat{{{0}}};
+ static constexpr std::array<std::array<Idx, 2>, 1> vec{{{0, 0}}};
+ static constexpr std::array<Real, 1> factors{1.};
+ };
+
+ template <> struct VoigtHelperData<2> {
+ static constexpr Int size{3};
+ static constexpr std::array<std::array<Idx, 2>, 2> mat{{{0, 2}, {3, 1}}};
+ static constexpr std::array<std::array<Idx, 2>, 4> vec{
+ {{0, 0}, {1, 1}, {0, 1}, {1, 0}}};
+ static constexpr std::array<Real, 3> factors{1., 1., 2.};
+ };
+
+ template <> struct VoigtHelperData<3> {
+ static constexpr Int size{6};
+ static constexpr std::array<std::array<Idx, 3>, 3> mat{
+ {{0, 5, 4}, {8, 1, 3}, {7, 6, 2}}};
+ static constexpr std::array<std::array<Idx, 2>, 9> vec{{{0, 0},
+ {1, 1},
+ {2, 2},
+ {1, 2},
+ {0, 2},
+ {0, 1},
+ {2, 1},
+ {2, 0},
+ {1, 0}}};
+ static constexpr std::array<Real, 6> factors{1., 1., 1., 2., 2., 2.};
+ };
+} // namespace details
+
/* -------------------------------------------------------------------------- */
-template <Int dim> class VoigtHelper {
+template <Int dim> class VoigtHelper : public details::VoigtHelperData<dim> {
static_assert(dim > 0U, "Cannot be < 1D");
static_assert(dim < 4U, "Cannot be > 3D");
+ using data = details::VoigtHelperData<dim>;
public:
/* ------------------------------------------------------------------------ */
template <class M, class V>
static constexpr inline void matrixToVoigt(M && matrix, V && vector);
template <class M>
static constexpr inline decltype(auto) matrixToVoigt(M && matrix);
template <class M, class V>
static constexpr inline void matrixToVoigtWithFactors(M && matrix,
V && vector);
template <class M>
static constexpr inline decltype(auto) matrixToVoigtWithFactors(M && matrix);
template <class M, class V>
static constexpr inline void voigtToMatrix(V && vector, M && matrix);
template <class V>
static constexpr inline decltype(auto) voigtToMatrix(V && vector);
/* ------------------------------------------------------------------------ */
/// transfer the B matrix to a Voigt notation B matrix
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)
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)
template <typename D1, typename D2, typename D3>
static constexpr inline void transferBMatrixToBL2(
- const Eigen::MatrixBase<D1> & B, const Eigen::MatrixBase<D2> & grad_u,
+ const Eigen::MatrixBase<D1> & dNdX, const Eigen::MatrixBase<D2> & grad_u,
Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element);
-
-public:
- static constexpr Int size{(dim * (dim - 1)) / 2 + dim};
- // matrix of vector index I as function of tensor indices i,j
- static const Idx mat[dim][dim];
- // array of matrix indices ij as function of vector index I
- 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 e29b6345f..266167efa 100644
--- a/src/common/aka_voigthelper_tmpl.hh
+++ b/src/common/aka_voigthelper_tmpl.hh
@@ -1,236 +1,239 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_voigthelper.hh" // NOLINT(pp_including_mainfile_in_preamble)
/* -------------------------------------------------------------------------- */
// #ifndef __AKANTU_AKA_VOIGTHELPER_TMPL_HH__
// #define __AKANTU_AKA_VOIGTHELPER_TMPL_HH__
namespace akantu {
-template <Int dim> constexpr Int VoigtHelper<dim>::size;
+// template <Int dim> constexpr Int VoigtHelper<dim>::size;
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class M, class V>
-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];
+constexpr inline void VoigtHelper<dim>::matrixToVoigt(
+ M && matrix, // NOLINT(cppcoreguidelines-missing-std-forward)
+ V && vector) { // NOLINT(cppcoreguidelines-missing-std-forward)
+ for (Int I = 0; I < data::size; ++I) {
+ auto && [i, j] = data::vec[I];
vector(I) = matrix(i, j);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class M>
constexpr inline decltype(auto) VoigtHelper<dim>::matrixToVoigt(M && matrix) {
- Vector<Real, size> vector;
+ Vector<Real, data::size> vector;
matrixToVoigt(std::forward<M>(matrix), vector);
return vector;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class M, class V>
-constexpr inline void VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix,
- V && vector) {
- for (Int I = 0; I < size; ++I) {
- auto i = vec[I][0];
- auto j = vec[I][1];
- vector(I) = factors[I] * matrix(i, j);
+constexpr inline void VoigtHelper<dim>::matrixToVoigtWithFactors(
+ M && matrix, // NOLINT(cppcoreguidelines-missing-std-forward)
+ V && vector) { // NOLINT(cppcoreguidelines-missing-std-forward)
+ for (Int I = 0; I < data::size; ++I) {
+ auto && [i, j] = data::vec[I];
+ vector(I) = data::factors[I] * matrix(i, j);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class M>
-constexpr inline decltype(auto) VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix) {
- Vector<Real, size> vector;
+constexpr inline decltype(auto)
+VoigtHelper<dim>::matrixToVoigtWithFactors(M && matrix) {
+ Vector<Real, data::size> vector;
matrixToVoigtWithFactors(std::forward<M>(matrix), vector);
return vector;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class M, class V>
-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];
+constexpr inline void VoigtHelper<dim>::voigtToMatrix(
+ V && vector, // NOLINT(cppcoreguidelines-missing-std-forward)
+ M && matrix) { // NOLINT(cppcoreguidelines-missing-std-forward)
+ for (Int I = 0; I < data::size; ++I) {
+ auto && [i, j] = data::vec[I];
matrix(i, j) = matrix(j, i) = vector(I);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class V>
constexpr inline decltype(auto) VoigtHelper<dim>::voigtToMatrix(V && vector) {
Matrix<Real, dim, dim> matrix;
voigtToMatrix(std::forward<V>(vector), matrix);
return matrix;
}
/* -------------------------------------------------------------------------- */
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 (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 (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 (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 <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 (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 <>
template <typename D1, typename D2, typename D3>
constexpr inline void VoigtHelper<1>::transferBMatrixToBL2(
- const Eigen::MatrixBase<D1> & B, const Eigen::MatrixBase<D2> & grad_u,
+ const Eigen::MatrixBase<D1> & dNdX, const Eigen::MatrixBase<D2> & grad_u,
Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element) {
Bvoigt.zero();
for (Int j = 0; j < nb_nodes_per_element; ++j) {
- Bvoigt(0, j) = grad_u(0, 0) * B(0, j);
+ Bvoigt(0, j) = grad_u(0, 0) * dNdX(0, j);
}
}
/* -------------------------------------------------------------------------- */
template <>
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 (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 (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) {
auto index1 = m;
auto index2 = 3 - m - aux;
Bvoigt(Iv, a * 3 + k) += grad_u(k, index1) * dNdX(index2, a);
}
}
}
}
}
}
/* -------------------------------------------------------------------------- */
template <>
template <typename D1, typename D2, typename D3>
constexpr inline void VoigtHelper<2>::transferBMatrixToBL2(
- const Eigen::MatrixBase<D1> & B, const Eigen::MatrixBase<D2> & grad_u,
+ const Eigen::MatrixBase<D1> & dNdX, const Eigen::MatrixBase<D2> & grad_u,
Eigen::MatrixBase<D3> & Bvoigt, Int nb_nodes_per_element) {
Bvoigt.zero();
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);
+ Bvoigt(i, j * 2 + k) = grad_u(k, i) * dNdX(i, j);
}
}
}
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);
+ Bvoigt(2, j * 2 + k) += grad_u(k, index1) * dNdX(index2, j);
}
}
}
}
} // namespace akantu
-//#endif /* __AKANTU_AKA_VOIGTHELPER_TMPL_HH__ */
+// #endif /* __AKANTU_AKA_VOIGTHELPER_TMPL_HH__ */
diff --git a/src/fe_engine/element_class_structural.hh b/src/fe_engine/element_class_structural.hh
index 86d2079ac..721c38215 100644
--- a/src/fe_engine/element_class_structural.hh
+++ b/src/fe_engine/element_class_structural.hh
@@ -1,302 +1,303 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "element_class.hh" // NOLINT(pp_including_mainfile_in_preamble)
/* -------------------------------------------------------------------------- */
#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 constexpr InterpolationKind kind{_itk_structural}; \
static constexpr Int nb_nodes_per_element{ \
InterpolationProperty<itp_geom_type>::nb_nodes_per_element}; \
static constexpr InterpolationType itp_geometry_type{itp_geom_type}; \
static constexpr Int natural_space_dimension{ \
InterpolationProperty<itp_geom_type>::natural_space_dimension}; \
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
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;
}
}
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);
N_T = N.block(0, 0, N_T.rows(), N_T.cols()) * T;
}
}
/// compute shape derivatives (input is dxds) for a set of points
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 = 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
*/
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))
+ 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
*/
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
*/
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 = 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;
}
};
/* -------------------------------------------------------------------------- */
/* 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(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
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 = dnds * Xs.transpose();
}
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));
}
}
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,
Xs.cols());
computeJMat(Xs, xs, Js);
for (auto && data : zip(jacobians, Js)) {
std::get<0>(data) = std::get<1>(data).determinant();
}
}
template <typename D1, typename D2>
static inline void computeRotation(const Eigen::MatrixBase<D1> & xs,
Eigen::MatrixBase<D2> & R);
public:
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_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"
+#include "element_class_hermite_inline_impl.hh" // NOLINT
/* keep order */
-#include "element_class_bernoulli_beam_inline_impl.hh"
-#include "element_class_kirchhoff_shell_inline_impl.hh"
+#include "element_class_bernoulli_beam_inline_impl.hh" // NOLINT(unused-includes)
+#include "element_class_kirchhoff_shell_inline_impl.hh" // NOLINT(unused-includes)
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_ELEMENT_CLASS_STRUCTURAL_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 7e7be3397..dba24de26 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,168 +1,168 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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" // NOLINT(pp_including_mainfile_in_preamble)
/* -------------------------------------------------------------------------- */
#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 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) {
+ 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);
+ // NOLINTNEXTLINE(readability-avoid-unconditional-preprocessor-if)
#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);
// clang-format off
// v1 t1 v2 t2
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
}
/* ---------------------------------------------------------------------- */
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 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 Eigen::MatrixBase<D1> & Xs, const Eigen::MatrixBase<D2> & xs,
- Eigen::MatrixBase<D3> & B) {
+ Eigen::MatrixBase<D3> & dnds) {
auto L = details::computeLength(xs);
- details::computeDNDS(Xs, L / 2, B);
+ details::computeDNDS(Xs, L / 2, dnds);
}
} // namespace akantu
#endif /* AKANTU_ELEMENT_CLASS_HERMITE_INLINE_IMPL_HH_ */
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 90e355f1f..09fd7ce14 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,158 +1,158 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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 D1, class D2,
aka::enable_if_t<aka::are_vectors<D1, D2>::value> *>
inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeShapes(
- const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &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 D1, class D2>
inline void InterpolationElement<_itp_lagrange_quadrangle_4>::computeDNDS(
- const Eigen::MatrixBase<D1> &c, Eigen::MatrixBase<D2> &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 <>
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);
+ 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/fe_engine.hh b/src/fe_engine/fe_engine.hh
index 535cfc082..24bc43b8c 100644
--- a/src/fe_engine/fe_engine.hh
+++ b/src/fe_engine/fe_engine.hh
@@ -1,366 +1,370 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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<Int> & filter_elements = empty_filter);
/// filter a field
template <typename T>
static void
filterElementalData(const Mesh & mesh, const Array<T> & quad_f,
Array<T> & filtered_f, ElementType type,
GhostType ghost_type = _not_ghost,
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, 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
+ [[nodiscard]] virtual Real
integrate(const Array<Real> & f, ElementType type,
GhostType ghost_type = _not_ghost,
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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
const Array<Idx> & filter_elements = empty_filter) const = 0;
/// integrate one element scalar value on all elements of type "type"
- Real integrate(const Ref<const VectorXr> f, const Element & element) const {
+ [[nodiscard]] 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;
+ [[nodiscard]] 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 Int
+ [[nodiscard]] 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,
- Idx id = 0) const = 0;
+ [[nodiscard]] const virtual Array<Real> &
+ getShapes(ElementType type, GhostType ghost_type = _not_ghost,
+ Idx id = 0) const = 0;
/// get the derivatives of shapes
- virtual const Array<Real> &
+ [[nodiscard]] virtual const Array<Real> &
getShapesDerivatives(ElementType type, GhostType ghost_type = _not_ghost,
Idx id = 0) const = 0;
/// get integration points
- virtual const MatrixXr &
+ [[nodiscard]] 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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
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<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<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, Int order_d,
ElementType type, GhostType ghost_type = _not_ghost,
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<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<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<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<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<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, 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, const GhostType ghost_type,
const ElementTypeMapArray<Idx> * element_filter) const = 0;
/// interpolate on a phyiscal point inside an element
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 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 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(Int dim = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind kind = _ek_regular) const;
+ [[nodiscard]] 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_AUTO(ElementDimension, element_dimension);
/// get the mesh contained in the fem object
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
template <class Derived>
- static inline Real
+ [[nodiscard]] static inline Real
getElementInradius(const Eigen::MatrixBase<Derived> & coord,
ElementType type);
- inline Real getElementInradius(const Element & element) const;
+ [[nodiscard]] 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 constexpr ElementType
+ [[nodiscard]] static inline constexpr ElementType
getCohesiveElementType(ElementType type_facet);
/// get igfem element type for a given regular type
- static inline Vector<ElementType> getIGFEMElementTypes(ElementType type);
+ [[nodiscard]] static inline Vector<ElementType>
+ getIGFEMElementTypes(ElementType type);
/// get the interpolation element associated to an element type
- static inline constexpr auto getInterpolationType(ElementType el_type);
+ [[nodiscard]] 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;
+ [[nodiscard]] 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;
+ [[nodiscard]] virtual const Integrator & getIntegratorInterface() const = 0;
AKANTU_GET_MACRO(ID, id, ID);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ID id;
/// spatial dimension of the problem
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_template.hh b/src/fe_engine/fe_engine_template.hh
index 7cac60d0b..b53502f77 100644
--- a/src/fe_engine/fe_engine_template.hh
+++ b/src/fe_engine/fe_engine_template.hh
@@ -1,479 +1,481 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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, Int spatial_dimension = _all_dimensions,
- const ID & id = "fem");
+ const ID & id = "fem", bool do_not_precompute = false);
~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, 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
+ [[nodiscard]] Real
integrate(const Array<Real> & f, ElementType type,
GhostType ghost_type = _not_ghost,
const Array<Idx> & filter_elements = empty_filter) const override;
/// integrate one element scalar value on all elements of type "type"
- Real integrate(const Ref<const VectorXr> f, ElementType type, Int index,
- GhostType ghost_type = _not_ghost) const override;
+ [[nodiscard]] 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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
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 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
- Int getNbIntegrationPoints(ElementType type,
- GhostType ghost_type = _not_ghost) const override;
+ [[nodiscard]] 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,
- Int id = 0) const override;
+ [[nodiscard]] const Array<Real> & getShapes(ElementType type,
+ GhostType ghost_type = _not_ghost,
+ Int id = 0) const override;
/// get the derivatives of shapes
- const Array<Real> & getShapesDerivatives(ElementType type,
- GhostType ghost_type = _not_ghost,
- Int id = 0) const override;
+ [[nodiscard]] const Array<Real> &
+ getShapesDerivatives(ElementType type, GhostType ghost_type = _not_ghost,
+ Int id = 0) const override;
/// get integration points
- inline const Matrix<Real> &
+ [[nodiscard]] 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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type = _not_ghost,
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<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<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, 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<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<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<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<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<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<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<Idx> * element_filter = nullptr) const override;
/// find natural coords from real coords provided an element
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, 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 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 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, 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;
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 {
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,
Int nb_degree_of_freedom, SparseMatrix & M,
Array<Real> * n,
ElementTypeMapArray<Real> & rotation_mat,
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<Idx> & /*unused*/,
const RemovedElementsEvent & /*unused*/) override;
void onElementsChanged(const Array<Element> & /*unused*/,
const Array<Element> & /*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_tmpl.hh b/src/fe_engine/fe_engine_template_tmpl.hh
index a0f085feb..925af4921 100644
--- a/src/fe_engine/fe_engine_template_tmpl.hh
+++ b/src/fe_engine/fe_engine_template_tmpl.hh
@@ -1,838 +1,843 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int spatial_dimension, const ID & id)
+ Mesh & mesh, Int spatial_dimension, const ID & id, bool do_not_precompute)
: FEEngine(mesh, spatial_dimension, id),
integrator(mesh, spatial_dimension, id),
- shape_functions(mesh, spatial_dimension, id) {}
+ shape_functions(mesh, spatial_dimension, id) {
+ if (not do_not_precompute) {
+ initShapeFunctions(_not_ghost);
+ initShapeFunctions(_ghost);
+ }
+}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::~FEEngineTemplate() =
default;
/* -------------------------------------------------------------------------- */
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,
Int nb_degree_of_freedom, ElementType type,
GhostType ghost_type,
const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
auto nb_points =
shape_functions.getIntegrationPoints(type, ghost_type).cols();
#ifndef AKANTU_NDEBUG
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.");
#endif
nablauq.resize(nb_element * nb_points);
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 (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();
}
/* -------------------------------------------------------------------------- */
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, Int nb_degree_of_freedom,
ElementType type, GhostType ghost_type,
const Array<Idx> & filter_elements) const {
auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
#ifndef AKANTU_NDEBUG
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);
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);
}
/* -------------------------------------------------------------------------- */
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<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
#ifndef AKANTU_NDEBUG
auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
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
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);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
Real FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::integrate(
const Ref<const VectorXr> f, ElementType type, Int index,
GhostType ghost_type) const {
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);
}
/* -------------------------------------------------------------------------- */
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,
Int nb_degree_of_freedom, ElementType type,
GhostType ghost_type,
const Array<Int> & filter_elements) const {
auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter)
nb_element = filter_elements.size();
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.");
intf.resize(nb_element * nb_quadrature_points);
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);
};
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,
Int nb_degree_of_freedom, ElementType type,
GhostType ghost_type,
const Array<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
auto nb_points =
shape_functions.getIntegrationPoints(type, ghost_type).cols();
auto nb_element = mesh.getNbElement(type, ghost_type);
if (filter_elements != empty_filter) {
nb_element = filter_elements.size();
}
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.");
uq.resize(nb_element * nb_points);
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<Idx> * filter_elements) const {
AKANTU_DEBUG_IN();
const Array<Idx> * filter = nullptr;
for (auto ghost_type : ghost_types) {
- for (const auto & type :
- uq.elementTypes(_all_dimensions, ghost_type, kind)) {
+ auto && types = uq.elementTypes(_all_dimensions, ghost_type, kind);
+ for (const auto & type : types) {
auto nb_quad_per_element = getNbIntegrationPoints(type, ghost_type);
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);
}
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();
}
/* -------------------------------------------------------------------------- */
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<Idx> & filter_elements) const {
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);
}
/* -------------------------------------------------------------------------- */
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, 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);
}
/* -------------------------------------------------------------------------- */
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<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);
}
/* -------------------------------------------------------------------------- */
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<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<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<Idx> & filter_elements) const {
const Array<Real> & nodes_coordinates = mesh.getNodes();
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<Idx> * element_filter) const {
AKANTU_DEBUG_IN();
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, 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, 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);
}
/* -------------------------------------------------------------------------- */
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);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::interpolate(
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) {
computeNormalsOnIntegrationPoints(mesh.getNodes(), ghost_type);
}
/* -------------------------------------------------------------------------- */
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().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 (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();
}
/* -------------------------------------------------------------------------- */
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,
GhostType ghost_type) const {
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, 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();
AKANTU_DEBUG_ASSERT(mesh.getSpatialDimension() == 1,
"Mesh dimension must be 1 to compute normals on points!");
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();
normal.resize(nb_element * nb_points);
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 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));
}
normal_value = difference / std::abs(difference);
}
for (Idx n(0); n < nb_points; ++n) {
(*normals_on_quad)(0, n) = normal_value;
}
++normals_on_quad;
}
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,
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);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline void FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::inverseMap(
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);
}
/* -------------------------------------------------------------------------- */
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, Int element, ElementType type,
GhostType ghost_type) const {
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);
}
/* -------------------------------------------------------------------------- */
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>::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);
}
/* -------------------------------------------------------------------------- */
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::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);
}
/* -------------------------------------------------------------------------- */
template <template <ElementKind, class> class I, template <ElementKind> class S,
ElementKind kind, class IntegrationOrderFunctor>
inline Int
FEEngineTemplate<I, S, kind, IntegrationOrderFunctor>::getNbIntegrationPoints(
ElementType type, GhostType ghost_type) const {
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);
}
/* -------------------------------------------------------------------------- */
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, Int /*id*/) const {
return shape_functions.getShapes(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
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, Int /*id*/) const {
return shape_functions.getShapesDerivatives(type, ghost_type);
}
/* -------------------------------------------------------------------------- */
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 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> & 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<Idx> & /*unused*/,
const ChangedElementsEvent & /*unused*/) {}
} // namespace akantu
diff --git a/src/fe_engine/integration_point.hh b/src/fe_engine/integration_point.hh
index df5463287..73bf11d3b 100644
--- a/src/fe_engine/integration_point.hh
+++ b/src/fe_engine/integration_point.hh
@@ -1,110 +1,107 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
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) {}
- constexpr IntegrationPoint(const IntegrationPoint & quad) = default;
- constexpr IntegrationPoint(IntegrationPoint && quad) = default;
-
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
inline auto operator==(const IntegrationPoint & quad) const -> bool {
return Element::operator==(quad) && this->num_point == quad.num_point;
}
inline auto operator!=(const IntegrationPoint & quad) const -> bool {
return Element::operator!=(quad) || (num_point != quad.num_point) ||
(global_num != quad.global_num);
}
auto operator<(const IntegrationPoint & rhs) const -> bool {
bool res = Element::operator<(rhs) ||
(Element::operator==(rhs) && this->num_point < rhs.num_point);
return res;
}
- inline auto operator=(const IntegrationPoint & q)
- -> IntegrationPoint & = default;
+ // inline auto operator=(const IntegrationPoint & q)
+ // -> IntegrationPoint & = default;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
public:
/// number of quadrature point in the element
Int num_point{0};
/// global number of the quadrature point
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 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_gauss.hh b/src/fe_engine/integrator_gauss.hh
index 57a60336d..47427a324 100644
--- a/src/fe_engine/integrator_gauss.hh
+++ b/src/fe_engine/integrator_gauss.hh
@@ -1,196 +1,199 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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,
- Int nb_degree_of_freedom, const Idx elem,
+ Int nb_degree_of_freedom, 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,
Int nb_degree_of_freedom, GhostType ghost_type,
const Array<Idx> & filter_elements) const;
/// integrate scalar field in_f
template <ElementType type, Int polynomial_degree>
- Real integrate(const Array<Real> & in_f,
- GhostType ghost_type = _not_ghost) const;
+ [[nodiscard]] 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, Idx index,
- GhostType ghost_type) const;
+ [[nodiscard]] 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<Idx> & filter_elements) const;
+ [[nodiscard]] Real integrate(const Array<Real> & in_f, GhostType ghost_type,
+ const Array<Idx> & filter_elements) const;
/// integrate a field without using the pre-computed values
template <ElementType type, Int polynomial_degree>
void integrate(const Array<Real> & in_f, Array<Real> & intf,
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,
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;
+ [[nodiscard]] const Matrix<Real> &
+ getIntegrationPoints(GhostType ghost_type) const;
/// return number of quadrature points
template <ElementType type>
- Int getNbIntegrationPoints(GhostType ghost_type) const;
+ [[nodiscard]] Int getNbIntegrationPoints(GhostType ghost_type) const;
+ template <ElementType type>
+ [[nodiscard]] Int getNbIntegrationPoints(GhostType ghost_type);
- template <ElementType type, Int n> Matrix<Real> getIntegrationPoints() const;
- template <ElementType type, Int n> Vector<Real> getIntegrationWeights() const;
+ template <ElementType type, Int n>
+ [[nodiscard]] Matrix<Real> getIntegrationPoints() const;
+ template <ElementType type, Int n>
+ [[nodiscard]] 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<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<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, Int polynomial_degree>
void multiplyJacobiansByWeights(
Array<Real> & jacobians,
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,
Int nb_degree_of_freedom,
const Array<Real> & jacobians,
Int nb_element) const;
void integrate(const Array<Real> & in_f, Array<Real> & intf,
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, 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<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(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 cb98b9716..cfc9b0546 100644
--- a/src/fe_engine/integrator_gauss_inline_impl.hh
+++ b/src/fe_engine/integrator_gauss_inline_impl.hh
@@ -1,626 +1,647 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
+#include "integrator_gauss.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, Int nb_degree_of_freedom,
- const Idx elem, GhostType ghost_type) const {
+ const Array<Real> & f, Real * intf, Int nb_degree_of_freedom, Idx elem,
+ GhostType ghost_type) const {
auto & jac_loc = jacobians(type, ghost_type);
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.");
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, Idx index, GhostType ghost_type) const {
const Array<Real> & jac_loc = jacobians(type, ghost_type);
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.");
auto * jac_val = jac_loc.data() + index * nb_quadrature_points;
- Real intf;
+ Real intf{};
integrate(in_f.data(), jac_val, &intf, 1, nb_quadrature_points);
return intf;
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
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));
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
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 ?");
+ if (not quadrature_points.exists(type, ghost_type)) {
+ constexpr auto polynomial_degree =
+ IntegrationOrderFunctor::template getOrder<type>();
+ return GaussIntegrationElement<type,
+ polynomial_degree>::getQuadraturePoints()
+ .cols();
+ }
+ return quadrature_points(type, ghost_type).cols();
+}
+
+/* -------------------------------------------------------------------------- */
+template <ElementKind kind, class IntegrationOrderFunctor>
+template <ElementType type>
+inline Int
+IntegratorGauss<kind, IntegrationOrderFunctor>::getNbIntegrationPoints(
+ GhostType ghost_type) {
+ if (not quadrature_points.exists(type, ghost_type)) {
+ this->template computeQuadraturePoints<type>(ghost_type);
+ }
return quadrature_points(type, ghost_type).cols();
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
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, 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) {
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, class D1, class D2, class D3>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::
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, 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 {
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 (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 << ")");
}
}
}
/* -------------------------------------------------------------------------- */
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<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);
jacobians.resize(nb_element * nb_quadrature_points);
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 = 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 (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);
}
computeJacobianOnQuadPointsByElement<type>(x, quad_points, *jacobians_it);
if (filter_elements == empty_filter) {
++jacobians_it;
}
}
}
/* -------------------------------------------------------------------------- */
#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<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();
auto nb_element = mesh.getNbElement(type, ghost_type);
jacobians.resize(nb_element * nb_quadrature_points);
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 = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin();
nb_element = x_el.size();
Array<Real> zeros(nb_element, spatial_dimension, 0.);
const auto has_extra_normal =
mesh.hasData<Real>("extra_normal", type, ghost_type);
auto extra_normal_begin = make_const_view(zeros, spatial_dimension).begin();
if (has_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 (Idx elem = 0; elem < nb_element; ++elem, ++x_it) {
if (filter_elements != empty_filter) {
jacobians_it = jacobians_begin + filter_elements(elem);
if (has_extra_normal) {
extra_normal = extra_normal_begin + filter_elements(elem);
}
}
const auto & X = *x_it;
auto & J = *jacobians_it;
Matrix<Real, nb_dofs, nb_dofs> R;
ElementClass<type>::computeRotationMatrix(R, X, *extra_normal);
const Int natural_space = ElementClass<type>::getNaturalSpaceDimension();
const Int nb_nodes = ElementClass<type>::getNbNodesPerElement();
// Extracting relevant lines
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;
if (has_extra_normal) {
++extra_normal;
}
}
}
}
#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<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);
jacobians.resize(nb_element * nb_quadrature_points);
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 = make_view(x_el, spatial_dimension, nb_nodes_per_element).begin();
auto nb_nodes_per_subelement = nb_nodes_per_element / 2;
Matrix<Real> x(spatial_dimension, nb_nodes_per_subelement);
nb_element = x_el.size();
Idx l_el = 0;
auto compute = [&](const auto & el) {
auto && J = jacobians_begin[el];
auto && X = x_it[l_el];
++l_el;
- for (Int n = 0; n < nb_nodes_per_subelement; ++n)
+ 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);
}
#endif
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
precomputeJacobiansOnQuadraturePoints(const Array<Real> & nodes,
GhostType 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);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type, Int polynomial_degree>
void IntegratorGauss<kind, IntegrationOrderFunctor>::multiplyJacobiansByWeights(
Array<Real> & jacobians, const Array<Int> & filter_elements) const {
constexpr auto nb_quadrature_points =
GaussIntegrationElement<type, polynomial_degree>::getNbQuadraturePoints();
auto && weights =
GaussIntegrationElement<type, polynomial_degree>::getWeights();
auto && view = make_view<nb_quadrature_points>(jacobians);
if (filter_elements != empty_filter) {
- for (auto && J : filter(filter_elements, view))
+ for (auto && J : filter(filter_elements, view)) {
J.array() *= weights.array();
+ }
} else {
- for (auto && J : view)
+ for (auto && J : view) {
J.array() *= weights.array();
+ }
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
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;
}
auto nb_points = jacobians.size() / 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))) {
// MatrixProxy<Real> f()
auto && f = std::get<0>(data);
auto && int_f = std::get<1>(data);
auto && J = std::get<2>(data);
int_f = f * J;
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
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 auto & jac_loc = jacobians(type, ghost_type);
if (filter_elements != empty_filter) {
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);
} else {
auto nb_element = mesh.getNbElement(type, ghost_type);
this->integrate(in_f, intf, nb_degree_of_freedom, jac_loc, nb_element);
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type, Int polynomial_degree>
void IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
const Array<Real> & in_f, Array<Real> & intf, Int nb_degree_of_freedom,
GhostType ghost_type) const {
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));
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type, Int polynomial_degree>
Real IntegratorGauss<kind, IntegrationOrderFunctor>::integrate(
const Array<Real> & in_f, GhostType ghost_type) const {
Array<Real> intfv(0, 1);
integrate<type, polynomial_degree>(in_f, intfv, 1, ghost_type);
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<Int> & filter_elements) const {
+ if (in_f.empty()) {
+ return 0;
+ }
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);
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,
Int nb_degree_of_freedom,
const Array<Real> & jacobians,
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 (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;
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
void IntegratorGauss<kind, IntegrationOrderFunctor>::
integrateOnIntegrationPoints(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 auto & jac_loc = this->jacobians(type, ghost_type);
if (filter_elements != empty_filter) {
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 {
auto nb_element = mesh.getNbElement(type, ghost_type);
this->integrateOnIntegrationPoints(in_f, intf, nb_degree_of_freedom,
jac_loc, nb_element);
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
template <ElementType type>
inline void
IntegratorGauss<kind, IntegrationOrderFunctor>::onElementsAddedByType(
const Array<Idx> & elements, GhostType ghost_type) {
const auto & nodes = mesh.getNodes();
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 auto polynomial_degree =
IntegrationOrderFunctor::template getOrder<type>();
this->multiplyJacobiansByWeights<type, polynomial_degree>(
this->jacobians(type, ghost_type), elements);
}
/* -------------------------------------------------------------------------- */
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) {
continue;
}
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 auto polynomial_degree =
IntegrationOrderFunctor::template getOrder<type>();
multiplyJacobiansByWeights<type, polynomial_degree>(
this->jacobians(type, ghost_type));
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind, class IntegrationOrderFunctor>
inline void IntegratorGauss<kind, IntegrationOrderFunctor>::initIntegrator(
const Array<Real> & nodes, ElementType type, GhostType ghost_type) {
tuple_dispatch<ElementTypes_t<kind>>(
[&](auto && enum_type) {
constexpr auto type = aka::decay_v<decltype(enum_type)>;
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<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/shape_functions.cc b/src/fe_engine/shape_functions.cc
index 2a0d1470c..71542c2bc 100644
--- a/src/fe_engine/shape_functions.cc
+++ b/src/fe_engine/shape_functions.cc
@@ -1,226 +1,222 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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<Idx> & element_filter) const {
AKANTU_DEBUG_IN();
auto spatial_dimension = this->mesh.getSpatialDimension();
auto nb_element = this->mesh.getNbElement(type, ghost_type);
- decltype(nb_element) nb_element_filter;
+ decltype(nb_element) nb_element_filter{};
if (element_filter == empty_filter) {
nb_element_filter = nb_element;
} else {
nb_element_filter = element_filter.size();
}
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);
}
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, nb_quad_per_element, nb_quad_per_element> quad_coord_matrix;
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 (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
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 = 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<Idx> * element_filter) const {
AKANTU_DEBUG_IN();
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) {
auto nb_element = mesh.getNbElement(type, ghost_type);
if (nb_element == 0) {
continue;
}
- const Array<Idx> * elem_filter;
+ const Array<Idx> * elem_filter = &(empty_filter);
if (element_filter != nullptr) {
elem_filter = &((*element_filter)(type, ghost_type));
- } else {
- elem_filter = &(empty_filter);
}
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<Idx> * element_filter) const {
AKANTU_DEBUG_IN();
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) {
auto nb_element = mesh.getNbElement(type, ghost_type);
if (nb_element == 0) {
continue;
}
- const Array<Idx> * elem_filter;
+ const Array<Idx> * elem_filter = &(empty_filter);
if (element_filter != nullptr) {
elem_filter = &((*element_filter)(type, ghost_type));
- } else {
- elem_filter = &(empty_filter);
}
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_inline_impl.hh b/src/fe_engine/shape_functions_inline_impl.hh
index 705a5086c..231f1f92e 100644
--- a/src/fe_engine/shape_functions_inline_impl.hh
+++ b/src/fe_engine/shape_functions_inline_impl.hh
@@ -1,336 +1,320 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_
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 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 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, class D1>
void ShapeFunctions::setIntegrationPointsByType(
const Eigen::MatrixBase<D1> & points, GhostType ghost_type) {
this->integration_points(type, ghost_type) = points;
}
/* -------------------------------------------------------------------------- */
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 (Int i = 0; i < coordinates.cols(); ++i) {
coordMatrix(i, 0) = 1;
}
break;
}
case 2: {
auto nb_quadrature_points = coordMatrix.cols();
for (Int i = 0; i < coordinates.cols(); ++i) {
coordMatrix(i, 0) = 1;
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> 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 <> 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 <> 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<Int> & element_filter) const {
AKANTU_DEBUG_IN();
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);
}
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_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 (auto && data :
+ for (auto && [el, field, itp_coord, inv_quad_coord] :
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
- */
- auto && inv_quad_coord_matrix = std::get<3>(data);
-
- /**
- * multiply it by the field values over quadrature points to get
- * the interpolation coefficients
- */
- coefficients = inv_quad_coord_matrix * std::get<1>(data).transpose();
-
- /// matrix containing the points' coordinates
- auto && coord = std::get<2>(data);
-
- auto el = std::get<0>(data);
- /// multiply the coordinates matrix by the coefficients matrix and store the
- /// result
- result_begin[el] = coefficients.transpose() * coord.transpose();
+
+ coefficients = inv_quad_coord * field.transpose();
+ result_begin[el] = coefficients.transpose() * itp_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<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() / nb_element;
auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
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 = std::make_unique<Array<Real>>(0, shapes.getNbComponent());
FEEngine::filterElementalData(mesh, shapes, *filtered_N, type, ghost_type,
filter_elements);
N_view = make_const_view(*filtered_N, nb_nodes_per_element, nb_points);
}
uq.resize(nb_element * nb_points);
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);
uq.noalias() = u * N;
}
}
/* -------------------------------------------------------------------------- */
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<Int> & filter_elements) const {
AKANTU_DEBUG_IN();
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 nb_element = mesh.getNbElement(type, ghost_type);
auto nb_degree_of_freedom = u_el.getNbComponent() / nb_nodes_per_element;
auto B_it = make_const_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 = make_const_view<element_dimension, nb_nodes_per_element>(*filtered_B)
.begin();
}
out_nablauq.resize(nb_element * nb_points);
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 (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.noalias() = u * B.transpose();
}
}
delete filtered_B;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
//#endif /* AKANTU_SHAPE_FUNCTIONS_INLINE_IMPL_HH_ */
diff --git a/src/fe_engine/shape_lagrange_inline_impl.hh b/src/fe_engine/shape_lagrange_inline_impl.hh
index 1d5839565..5eb131030 100644
--- a/src/fe_engine/shape_lagrange_inline_impl.hh
+++ b/src/fe_engine/shape_lagrange_inline_impl.hh
@@ -1,540 +1,544 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <typename D>
inline void ShapeLagrange<kind>::initShapeFunctions(
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) {
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);
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type, typename D1, typename D2>
inline void ShapeLagrange<kind>::computeShapeDerivativesOnCPointsByElement(
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, 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();
// as advised by the Eigen developers even though this is a UB
auto & natural_coords = const_cast<Eigen::MatrixBase<D2> &>(natural_coords_);
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, 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, 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, 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();
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, typename D>
void ShapeLagrange<kind>::computeShapeDerivatives(
const Eigen::MatrixBase<D> & real_coords, Idx elem,
Tensor3Base<Real> & shapesd, GhostType ghost_type) const {
AKANTU_DEBUG_IN();
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 (Int i = 0; i < nb_points; i++) {
inverseMap<type>(real_coords(i), elem, natural_coords(i), ghost_type);
}
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, Int spatial_dimension,
const ID & id)
: ShapeLagrangeBase(mesh, spatial_dimension, kind, id) {}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type, typename D>
void ShapeLagrange<kind>::computeShapeDerivativesOnIntegrationPoints(
const Array<Real> & nodes, const Eigen::MatrixBase<D> & integration_points,
Array<Real> & shape_derivatives, GhostType ghost_type,
const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
auto spatial_dimension = mesh.getSpatialDimension();
auto nb_nodes_per_element =
ElementClass<type>::getNbNodesPerInterpolationElement();
auto nb_points = integration_points.cols();
auto nb_element = mesh.getConnectivity(type, ghost_type).size();
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);
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 (Int elem = 0; elem < nb_element; ++elem, ++x_it) {
if (filter_elements != empty_filter) {
shapesd_val = shape_derivatives.data() +
filter_elements(elem) * size_of_shapesd * 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 Ref<const MatrixXr> integration_points,
Array<Real> & shape_derivatives, ElementType type, GhostType ghost_type,
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);
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);
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, Int nb_degree_of_freedom,
const Array<Real> & shapes, GhostType ghost_type,
const Array<Idx> & filter_elements) const {
AKANTU_DEBUG_IN();
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, 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,
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));
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<Idx> & filter_elements) const {
+ BtDs.resize(Ds.size());
+
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_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);
view = make_const_view(shapes_derivatives_filtered, spatial_dimension,
nb_nodes_per_element);
}
for (auto && values :
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.noalias() = D * B;
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <
ElementType type,
std::enable_if_t<ElementClass<type>::getNaturalSpaceDimension() != 0> *>
void ShapeLagrange<kind>::computeBtDB(
const Array<Real> & Ds, Array<Real> & BtDBs, Int order_d,
GhostType ghost_type, const Array<Idx> & filter_elements) const {
+ BtDBs.resize(Ds.size());
+
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_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);
view =
make_const_view(shapes_derivatives_filtered, dim, nb_nodes_per_element);
}
if (order_d == 4) {
auto tangent_size = VoigtHelper<dim>::size;
Matrix<Real> B(tangent_size, 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_B.noalias() = B.transpose() * D * B;
}
} else if (order_d == 2) {
for (auto && values :
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_B.noalias() = B.transpose() * D * B;
}
}
}
/* -------------------------------------------------------------------------- */
template <ElementKind kind>
template <ElementType type>
void ShapeLagrange<kind>::computeNtbN(
const Array<Real> & bs, Array<Real> & NtbNs, GhostType ghost_type,
const Array<Idx> & filter_elements) const {
+ NtbNs.resize(bs.size());
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_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);
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(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_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<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_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);
view = make_const_view(shapes_filtered, 1, size_of_shapes);
}
for (auto && values :
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.noalias() = b * N;
}
AKANTU_DEBUG_OUT();
}
} // namespace akantu
#endif /* AKANTU_SHAPE_LAGRANGE_INLINE_IMPL_HH_ */
diff --git a/src/io/dumper/dumpable.hh b/src/io/dumper/dumpable.hh
index 65ed08698..bd620974c 100644
--- a/src/io/dumper/dumpable.hh
+++ b/src/io/dumper/dumpable.hh
@@ -1,31 +1,30 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_DUMPABLE_HH_
#define AKANTU_DUMPABLE_HH_
#include "dumpable_iohelper.hh"
+#include "dumpable_inline_impl.hh"
+
#endif /* AKANTU_DUMPABLE_HH_ */
diff --git a/src/io/dumper/dumpable_iohelper.hh b/src/io/dumper/dumpable_iohelper.hh
index 2cc73ee25..ce1c388a8 100644
--- a/src/io/dumper/dumpable_iohelper.hh
+++ b/src/io/dumper/dumpable_iohelper.hh
@@ -1,182 +1,187 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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();
+ /* ------------------------------------------------------------------------ */
+ Dumpable(const Dumpable & /*other*/) = default;
+ Dumpable(Dumpable && /*other*/) = default;
+ Dumpable & operator=(const Dumpable & /*other*/) = default;
+ Dumpable & operator=(Dumpable && /*other*/) = default;
+ /* ------------------------------------------------------------------------ */
+
/* ------------------------------------------------------------------------ */
/* 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, 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,
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<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,
+ void addDumpFilteredMeshToDumper(
+ const std::string & dumper_name, const Mesh & mesh,
const ElementTypeMapArray<Idx> & elements_filter,
- const Array<Idx> & nodes_filter,
- Int spatial_dimension = _all_dimensions,
+ 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,
- Int 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,
- Int 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(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, 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;
+ [[nodiscard]] 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/parser/algebraic_parser.hh b/src/io/parser/algebraic_parser.hh
index b8017d267..357fa2f03 100644
--- a/src/io/parser/algebraic_parser.hh
+++ b/src/io/parser/algebraic_parser.hh
@@ -1,515 +1,515 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
// Boost
#include <boost/config/warning_disable.hpp>
-#include <boost/spirit/include/phoenix.hpp>
+#include <boost/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 (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(), cols);
tmp.fill(0.);
it_rows = _cells.begin();
for (Int i = 0; it_rows != _cells.end(); ++it_rows, ++i) {
auto it_cols = it_rows->_cells.begin();
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 =
RandomDistributionType::_not_defined,
const parsable_vector & parameters = parsable_vector())
: base(base), type(type), parameters(parameters) {}
Real base{0.};
RandomDistributionType type{RandomDistributionType::_not_defined};
parsable_vector parameters;
};
inline std::ostream & operator<<(std::ostream & stream,
const ParsableRandomGenerator & prg) {
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];
/* clang-format off */
generator_type.add
("uniform" , RandomDistributionType::_uniform )
("exponential" , RandomDistributionType::_exponential )
("gamma" , RandomDistributionType::_gamma )
("weibull" , RandomDistributionType::_weibull )
("extreme_value", RandomDistributionType::_extreme_value)
("normal" , RandomDistributionType::_normal )
("lognormal" , RandomDistributionType::_lognormal )
("chi_squared" , RandomDistributionType::_chi_squared )
("cauchy" , RandomDistributionType::_cauchy )
("fisher_f" , RandomDistributionType::_fisher_f )
("student_t" , RandomDistributionType::_student_t );
/* clang-format on */
#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/input_file_parser.hh b/src/io/parser/input_file_parser.hh
index c27bb90d4..2242a3d0f 100644
--- a/src/io/parser/input_file_parser.hh
+++ b/src/io/parser/input_file_parser.hh
@@ -1,260 +1,260 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
// Boost
/* -------------------------------------------------------------------------- */
#include <boost/config/warning_disable.hpp>
-#include <boost/spirit/include/phoenix_bind.hpp>
-#include <boost/spirit/include/phoenix_core.hpp>
-#include <boost/spirit/include/phoenix_fusion.hpp>
-#include <boost/spirit/include/phoenix_operator.hpp>
+#include <boost/phoenix/bind.hpp>
+#include <boost/phoenix/core.hpp>
+#include <boost/phoenix/fusion.hpp>
+#include <boost/phoenix/operator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant/recursive_variant.hpp>
#ifndef AKANTU_INPUT_FILE_PARSER_HH_
#define AKANTU_INPUT_FILE_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 error_handler_ {
template <typename, typename, typename, typename> struct result {
using type = void;
};
template <typename Iterator>
void operator()(qi::info const & what, Iterator err_pos, Iterator /*first*/,
Iterator /*last*/) const {
spirit::classic::file_position pos = err_pos.get_position();
AKANTU_EXCEPTION("Parse error [ "
<< "Expecting " << what << " instead of \"" << *err_pos
<< "\" ]"
<< " in file " << pos.file << " line " << pos.line
<< " column " << pos.column << std::endl
<< "'" << err_pos.get_currentline() << "'" << std::endl
<< std::setw(pos.column) << " "
<< "^- here");
}
private:
};
static ParserSection & create_subsection(
const ParserType & type, const boost::optional<std::string> & opt_name,
const boost::optional<std::string> & opt_option, ParserSection & sect) {
std::string option;
if (opt_option) {
option = *opt_option;
}
static size_t id = 12;
std::string name = "anonymous_" + std::to_string(id++);
if (opt_name) {
name = *opt_name;
}
ParserSection sect_tmp(name, type, option, sect);
return sect.addSubSection(sect_tmp);
}
template <typename Iter>
static bool create_parameter(boost::iterator_range<Iter> & rng,
std::string & value, ParserSection & sect) {
try {
std::string name(rng.begin(), rng.end());
name = trim(name);
spirit::classic::file_position pos = rng.begin().get_position();
ParserParameter param_tmp(name, value, sect);
param_tmp.setDebugInfo(pos.file, pos.line, pos.column);
sect.addParameter(param_tmp);
} catch (debug::Exception & e) {
return false;
}
return true;
}
static std::string concatenate(const std::string & t1,
const std::string & t2) {
return (t1 + t2);
}
/* ---------------------------------------------------------------------- */
/* Grammars definitions */
/* ---------------------------------------------------------------------- */
template <class Iterator>
struct InputFileGrammar
: qi::grammar<Iterator, void(), typename Skipper<Iterator>::type> {
InputFileGrammar(ParserSection * sect)
: InputFileGrammar::base_type(start, "input_file_grammar"),
parent_section(sect) {
/* clang-format off */
start
= mini_section(parent_section)
;
mini_section
= *(
entry (lbs::_r1)
| section(lbs::_r1)
)
;
entry
= (
qi::raw[key]
>> '='
> value
) [ lbs::_pass = phx::bind(&create_parameter<Iterator>,
lbs::_1,
lbs::_2,
*lbs::_r1) ]
;
section
= (
qi::no_case[section_type]
> qi::lexeme
[
-section_name
> -section_option
]
) [ lbs::_a = &phx::bind(&create_subsection,
lbs::_1,
phx::at_c<0>(lbs::_2),
phx::at_c<1>(lbs::_2),
*lbs::_r1) ]
> '['
> mini_section(lbs::_a)
> ']'
;
section_name
= qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9")
;
section_option
= (+ascii::space >> section_name) [ lbs::_val = lbs::_2 ]
;
key
= qi::char_("a-zA-Z_") >> *qi::char_("a-zA-Z_0-9")
;
value
= (
mono_line_value [ lbs::_a = phx::bind(&concatenate, lbs::_a, lbs::_1) ]
> *(
'\\' > mono_line_value [ lbs::_a = phx::bind(&concatenate, lbs::_a, lbs::_1) ]
)
) [ lbs::_val = lbs::_a ]
;
mono_line_value
= qi::lexeme
[
+(qi::char_ - (qi::char_('=') | spirit::eol | '#' | ';' | '\\'))
]
;
skipper
= ascii::space
| "#" >> *(qi::char_ - spirit::eol)
;
/* clang-format on */
#define AKANTU_SECTION_TYPE_ADD(r, data, elem) \
(BOOST_PP_STRINGIZE(elem), BOOST_PP_CAT(ParserType::_, elem))
section_type.add BOOST_PP_SEQ_FOR_EACH(AKANTU_SECTION_TYPE_ADD, _,
AKANTU_SECTION_TYPES);
#undef AKANTU_SECTION_TYPE_ADD
#if !defined(AKANTU_NDEBUG)
phx::function<error_handler_> const error_handler = error_handler_();
qi::on_error<qi::fail>(start,
error_handler(lbs::_4, lbs::_3, lbs::_1, lbs::_2));
#endif
section.name("section");
section_name.name("section-name");
section_option.name("section-option");
mini_section.name("section-content");
entry.name("parameter");
key.name("parameter-name");
value.name("parameter-value");
section_type.name("section-types-list");
mono_line_value.name("mono-line-value");
#if !defined AKANTU_NDEBUG
if (AKANTU_DEBUG_TEST(dblDebug)) {
// qi::debug(section);
qi::debug(section_name);
qi::debug(section_option);
// qi::debug(mini_section);
// qi::debug(entry);
qi::debug(key);
qi::debug(value);
qi::debug(mono_line_value);
}
#endif
}
const std::string & getErrorMessage() const { return error_message; };
using skipper_type = typename Skipper<Iterator>::type;
skipper_type skipper;
private:
std::string error_message;
qi::rule<Iterator, void(ParserSection *), skipper_type> mini_section;
qi::rule<Iterator, void(ParserSection *), qi::locals<ParserSection *>,
skipper_type>
section;
qi::rule<Iterator, void(), skipper_type> start;
qi::rule<Iterator, std::string()> section_name;
qi::rule<Iterator, std::string()> section_option;
qi::rule<Iterator, void(ParserSection *), skipper_type> entry;
qi::rule<Iterator, std::string(), skipper_type> key;
qi::rule<Iterator, std::string(), qi::locals<std::string>, skipper_type>
value;
qi::rule<Iterator, std::string(), skipper_type> mono_line_value;
qi::symbols<char, ParserType> section_type;
ParserSection * parent_section;
};
} // namespace parser
} // namespace akantu
#endif /* AKANTU_INPUT_FILE_PARSER_HH_ */
diff --git a/src/io/parser/parser.hh b/src/io/parser/parser.hh
index d31a51b8b..db8584720 100644
--- a/src/io/parser/parser.hh
+++ b/src/io/parser/parser.hh
@@ -1,534 +1,535 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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) \
+ (constitutive_law) \
(mesh) \
(model) \
(model_solver) \
(neighborhood) \
(neighborhoods) \
(non_linear_solver) \
(non_local) \
(rules) \
(solver) \
(time_step_solver) \
(user) \
(weight_function) \
(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, Int line, Int column) {
dbg_filename = filename;
dbg_line = line;
dbg_column = column;
}
template <typename T> inline operator 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
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
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_random.cc b/src/io/parser/parser_random.cc
deleted file mode 100644
index 4663d763c..000000000
--- a/src/io/parser/parser_random.cc
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * 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(__INTEL_COMPILER)
-//#pragma warning ( disable : 383 )
-#elif defined(__clang__) // test clang to be sure that when we test for gnu it
-// is only gnu
-#elif (defined(__GNUC__) || defined(__GNUG__))
-#define GCC_VERSION \
- (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-#if GCC_VERSION > 40600
-#pragma GCC diagnostic push
-#endif
-#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
-#endif
-
-/* -------------------------------------------------------------------------- */
-#include "parser.hh"
-#if !defined(DOXYGEN)
-#include "parser_grammar_tmpl.hh"
-/* -------------------------------------------------------------------------- */
-#include "algebraic_parser.hh"
-#endif
-/* -------------------------------------------------------------------------- */
-
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-RandomParameter<Real>
-Parser::parseRandomParameter(const std::string & value,
- const ParserSection & section) {
-#if !defined(DOXYGEN)
- using boost::spirit::ascii::space_type;
- parser::RandomGeneratorGrammar<std::string::const_iterator, space_type>
- grammar(section);
- grammar.name("random_grammar");
- parser::ParsableRandomGenerator rg =
- Parser::parseType<parser::ParsableRandomGenerator>(value, grammar);
-
- Vector<Real> params = rg.parameters;
- switch (params.size()) {
- case 0:
- return make_random_parameter(rg.base, rg.type);
- case 1:
- return make_random_parameter(rg.base, rg.type, params(0));
- case 2:
- return make_random_parameter(rg.base, rg.type, params(0), params(1));
- }
-
- return make_random_parameter(rg.base, rg.type);
-#endif
-}
-
-/* -------------------------------------------------------------------------- */
-
-} // namespace akantu
diff --git a/src/io/parser/parser_real.cc b/src/io/parser/parser_real.cc
index 04d574012..d7265f490 100644
--- a/src/io/parser/parser_real.cc
+++ b/src/io/parser/parser_real.cc
@@ -1,54 +1,99 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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(__INTEL_COMPILER)
-//#pragma warning ( disable : 383 )
+// #pragma warning ( disable : 383 )
#elif defined(__clang__) // test clang to be sure that when we test for gnu it
// is only gnu
#elif (defined(__GNUC__) || defined(__GNUG__))
#define GCC_VERSION \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION > 40600
#pragma GCC diagnostic push
#endif
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
/* -------------------------------------------------------------------------- */
#include "parser.hh"
#include "parser_grammar_tmpl.hh"
/* -------------------------------------------------------------------------- */
#include "algebraic_parser.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
Real Parser::parseReal(const std::string & value,
const ParserSection & section) {
using boost::spirit::ascii::space_type;
parser::AlgebraicGrammar<std::string::const_iterator, space_type> grammar(
section);
grammar.name("algebraic_grammar");
return Parser::parseType<Real>(value, grammar);
}
+/* -------------------------------------------------------------------------- */
+RandomParameter<Real>
+Parser::parseRandomParameter(const std::string & value,
+ const ParserSection & section) {
+#if !defined(DOXYGEN)
+ using boost::spirit::ascii::space_type;
+ parser::RandomGeneratorGrammar<std::string::const_iterator, space_type>
+ grammar(section);
+ grammar.name("random_grammar");
+ auto rg = Parser::parseType<parser::ParsableRandomGenerator>(value, grammar);
+
+ Vector<Real> params = rg.parameters;
+ switch (params.size()) {
+ case 0:
+ return make_random_parameter(rg.base, rg.type);
+ case 1:
+ return make_random_parameter(rg.base, rg.type, params(0));
+ case 2:
+ return make_random_parameter(rg.base, rg.type, params(0), params(1));
+ }
+
+ return make_random_parameter(rg.base, rg.type);
+#endif
+}
+
+/* -------------------------------------------------------------------------- */
+Vector<Real> Parser::parseVector(const std::string & value,
+ const ParserSection & section) {
+ using boost::spirit::ascii::space_type;
+ parser::VectorGrammar<std::string::const_iterator, space_type> grammar(
+ section);
+ grammar.name("vector_grammar");
+ return Parser::parseType<parser::parsable_vector>(value, grammar);
+}
+
+/* -------------------------------------------------------------------------- */
+Matrix<Real> Parser::parseMatrix(const std::string & value,
+ const ParserSection & section) {
+ using boost::spirit::ascii::space_type;
+ parser::MatrixGrammar<std::string::const_iterator, space_type> grammar(
+ section);
+ grammar.name("matrix_grammar");
+ return Parser::parseType<parser::parsable_matrix>(value, grammar);
+}
+
} // namespace akantu
diff --git a/src/io/parser/parser_types.cc b/src/io/parser/parser_types.cc
deleted file mode 100644
index 62c99f519..000000000
--- a/src/io/parser/parser_types.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * 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(__INTEL_COMPILER)
-//#pragma warning ( disable : 383 )
-#elif defined(__clang__) // test clang to be sure that when we test for gnu it
-// is only gnu
-#elif (defined(__GNUC__) || defined(__GNUG__))
-#define GCC_VERSION \
- (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
-#if GCC_VERSION > 40600
-#pragma GCC diagnostic push
-#endif
-#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
-#endif
-
-/* -------------------------------------------------------------------------- */
-#include "parser.hh"
-#include "parser_grammar_tmpl.hh"
-/* -------------------------------------------------------------------------- */
-#include "algebraic_parser.hh"
-/* -------------------------------------------------------------------------- */
-
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-Vector<Real> Parser::parseVector(const std::string & value,
- const ParserSection & section) {
- using boost::spirit::ascii::space_type;
- parser::VectorGrammar<std::string::const_iterator, space_type> grammar(
- section);
- grammar.name("vector_grammar");
- return Parser::parseType<parser::parsable_vector>(value, grammar);
-}
-
-/* -------------------------------------------------------------------------- */
-Matrix<Real> Parser::parseMatrix(const std::string & value,
- const ParserSection & section) {
- using boost::spirit::ascii::space_type;
- parser::MatrixGrammar<std::string::const_iterator, space_type> grammar(
- section);
- grammar.name("matrix_grammar");
- return Parser::parseType<parser::parsable_matrix>(value, grammar);
-}
-
-/* -------------------------------------------------------------------------- */
-
-} // namespace akantu
diff --git a/src/mesh/element_group.cc b/src/mesh/element_group.cc
index 4a9a309b2..d73c06f64 100644
--- a/src/mesh/element_group.cc
+++ b/src/mesh/element_group.cc
@@ -1,205 +1,205 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_accessor.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, 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 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);
-
+ if (not elements.exists(type, ghost_type)) {
+ elements.alloc(0, 1, type, ghost_type);
+ }
+ auto & elem_list = elements(type, ghost_type);
auto nb_elem = elem_list.size();
/// append new elements to current list
elem_list.resize(nb_elem + nb_other_elem);
std::copy(other_elem_list.begin(), other_elem_list.end(),
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;
+ stream << space << "ElementGroup ["
+ << "\n";
+ stream << space << " + name: " << name << "\n";
+ stream << space << " + dimension: " << dimension << "\n";
elements.printself(stream, indent + 1);
node_group.printself(stream, indent + 1);
- stream << space << "]" << std::endl;
+ stream << space << "]"
+ << "\n";
}
/* -------------------------------------------------------------------------- */
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 (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);
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(Int dimension) {
this->dimension = std::max(dimension, this->dimension);
}
/* -------------------------------------------------------------------------- */
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();
for (auto ghost_type : ghost_types) {
for (auto type : elements.elementTypes(_ghost_type = ghost_type)) {
auto & els = elements(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();
for (auto element : els) {
auto && conn = conn_it[element];
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 69de1eb89..7b009d722 100644
--- a/src/mesh/element_group.hh
+++ b/src/mesh/element_group.hh
@@ -1,184 +1,183 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int dimension = _all_dimensions,
const std::string & id = "element_group");
- ElementGroup(const ElementGroup & /*unused*/);
-
/* ------------------------------------------------------------------------ */
/* Type definitions */
/* ------------------------------------------------------------------------ */
public:
using ElementList = ElementTypeMapArray<Idx>;
/* ------------------------------------------------------------------------ */
/* Element iterator */
/* ------------------------------------------------------------------------ */
using type_iterator = ElementList::type_iterator;
template <typename... pack>
[[nodiscard]] inline decltype(auto) elementTypes(pack &&... _pack) const {
- return elements.elementTypes(_pack...);
+ return elements.elementTypes(std::forward<decltype(_pack)>(_pack)...);
}
[[nodiscard]] inline auto begin(ElementType type,
GhostType ghost_type = _not_ghost) const;
[[nodiscard]] 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);
[[nodiscard]] bool empty() const;
/// 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, Idx element,
GhostType ghost_type = _not_ghost, bool add_nodes = true,
bool check_for_duplicate = true);
inline void addNode(Idx node_id, bool check_for_duplicate = true);
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(Int dimension);
void onNodesAdded(const Array<Idx> & new_nodes, const NewNodesEvent & event);
private:
inline void addElement(ElementType elem_type, Idx elem_id,
GhostType ghost_type);
friend class GroupManager;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- const Array<Idx> & getElements(ElementType type,
- GhostType ghost_type = _not_ghost) const;
+ [[nodiscard]] 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;
+ [[nodiscard]] decltype(auto)
+ getElementsIterable(ElementType type,
+ GhostType ghost_type = _not_ghost) const;
// AKANTU_GET_MACRO(Nodes, node_group.getNodes(), const Array<UInt> &);
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);
- inline Int getNbNodes() const;
+ [[nodiscard]] 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
Int dimension{_all_dimensions};
/// empty arry for the iterator to work when an element type not present
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_type_map.cc b/src/mesh/element_type_map.cc
index 93697fae3..40429eba6 100644
--- a/src/mesh/element_type_map.cc
+++ b/src/mesh/element_type_map.cc
@@ -1,60 +1,75 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int nb_component, Int spatial_dimension,
- GhostType ghost_type, ElementKind element_kind)
- : MeshElementTypeMapArrayInitializer(
- fe_engine.getMesh(), nb_component,
- spatial_dimension == -2 ? fe_engine.getMesh().getSpatialDimension()
- : spatial_dimension,
- ghost_type, element_kind, true, false),
- fe_engine(fe_engine) {}
+ GhostType ghost_type, ElementKind element_kind,
+ const ElementTypeMapArray<Idx> * filter)
+ : FEEngineElementTypeMapArrayInitializer(
+ fe_engine,
+ [nb_component](auto && /*type*/, auto && /*ghost_type*/) {
+ return nb_component;
+ },
+ spatial_dimension, ghost_type, element_kind, filter) {}
FEEngineElementTypeMapArrayInitializer::FEEngineElementTypeMapArrayInitializer(
const FEEngine & fe_engine,
const ElementTypeMapArrayInitializer::CompFunc & nb_component,
- Int spatial_dimension, GhostType ghost_type, ElementKind element_kind)
+ Int /*spatial_dimension*/, GhostType ghost_type, ElementKind element_kind,
+ const ElementTypeMapArray<Idx> * filter)
: MeshElementTypeMapArrayInitializer(
- fe_engine.getMesh(), nb_component,
- spatial_dimension == -2 ? fe_engine.getMesh().getSpatialDimension()
- : spatial_dimension,
- ghost_type, element_kind, true, false),
+ fe_engine.getMesh(), nb_component, fe_engine.getElementDimension(),
+ ghost_type, element_kind, true, false, filter),
fe_engine(fe_engine) {}
Int FEEngineElementTypeMapArrayInitializer::size(ElementType type) const {
- return MeshElementTypeMapArrayInitializer::size(type) *
- fe_engine.getNbIntegrationPoints(type, this->ghost_type);
+ auto size = MeshElementTypeMapArrayInitializer::size(type);
+ if (size != 0) {
+ return size * fe_engine.getNbIntegrationPoints(type, this->ghost_type);
+ }
+
+ return 0;
}
-FEEngineElementTypeMapArrayInitializer::ElementTypesIteratorHelper
-FEEngineElementTypeMapArrayInitializer::elementTypes() const {
- return this->fe_engine.elementTypes(spatial_dimension, ghost_type,
- element_kind);
+auto FEEngineElementTypeMapArrayInitializer::elementTypes() const
+ -> std::vector<ElementType> {
+ std::vector<ElementType> types;
+ if (this->filter != nullptr) {
+ for (auto type : this->filter->elementTypes(spatial_dimension, ghost_type,
+ element_kind)) {
+ types.emplace_back(type);
+ }
+ return types;
+ }
+ for (auto type : this->fe_engine.elementTypes(spatial_dimension, ghost_type,
+ element_kind)) {
+ types.emplace_back(type);
+ }
+ return types;
}
} // namespace akantu
diff --git a/src/mesh/element_type_map.hh b/src/mesh/element_type_map.hh
index 7ae89dbdf..c11c301f6 100644
--- a/src/mesh/element_type_map.hh
+++ b/src/mesh/element_type_map.hh
@@ -1,494 +1,480 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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:
+ ElementTypeMapBase() = default;
+ ElementTypeMapBase(const ElementTypeMapBase &) = default;
+ ElementTypeMapBase(ElementTypeMapBase &&) = default;
+ ElementTypeMapBase & operator=(const ElementTypeMapBase &) = default;
+ ElementTypeMapBase & operator=(ElementTypeMapBase &&) = default;
virtual ~ElementTypeMapBase() = default;
};
/* -------------------------------------------------------------------------- */
/* ElementTypeMap */
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
class ElementTypeMap : public ElementTypeMapBase {
public:
using value_type = Stored;
- ElementTypeMap();
- ~ElementTypeMap() override;
+ ElementTypeMap() = default;
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 auto exists(SupportType type, GhostType ghost_type = _not_ghost) const
+ [[nodiscard]] 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 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 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 insertee 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 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 = 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,
Int dim, ElementKind ek);
-
- type_iterator(const type_iterator & it);
type_iterator() = default;
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;
- Int dim;
- ElementKind kind;
+ Int dim{_all_dimensions};
+ ElementKind kind{_ek_not_defined};
};
/// 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, Int dim,
+ ElementTypesIteratorHelper(const ElementTypeMap & 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;
- auto operator=(const ElementTypesIteratorHelper &)
- -> ElementTypesIteratorHelper & = default;
- auto operator=(ElementTypesIteratorHelper &&) noexcept
- -> ElementTypesIteratorHelper & = default;
-
- auto begin() -> iterator;
- auto end() -> iterator;
+ auto begin() -> type_iterator;
+ auto end() -> type_iterator;
private:
- std::reference_wrapper<const Container> container;
- Int dim;
- GhostType ghost_type;
- ElementKind kind;
+ std::reference_wrapper<const ElementTypeMap> container;
+ Int dim{_all_dimensions};
+ GhostType ghost_type{_not_ghost};
+ ElementKind kind{_ek_not_defined};
};
-private:
- auto elementTypesImpl(Int dim = _all_dimensions,
- GhostType ghost_type = _not_ghost,
- ElementKind kind = _ek_not_defined) const
+protected:
+ [[nodiscard]] virtual auto
+ elementTypesImpl(Int dim = _all_dimensions, GhostType ghost_type = _not_ghost,
+ ElementKind kind = _ek_not_defined) const
-> ElementTypesIteratorHelper;
- template <typename... pack>
- 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>
- auto elementTypes(pack &&... _pack) const
+ [[nodiscard]] 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)...);
+ return elementTypesImpl(
+ OPTIONAL_NAMED_ARG(spatial_dimension, _all_dimensions),
+ OPTIONAL_NAMED_ARG(ghost_type, _not_ghost),
+ OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined));
}
- template <typename... pack>
- auto elementTypes(pack &&... _pack) const
- -> std::enable_if_t<not are_named_argument<pack...>::value,
- ElementTypesIteratorHelper> {
- return elementTypesImpl(std::forward<decltype(_pack)>(_pack)...);
+ [[nodiscard]] auto elementTypes(Int dim, GhostType ghost_type = _not_ghost,
+ ElementKind kind = _ek_not_defined) const {
+ return elementTypesImpl(dim, ghost_type, kind);
+ }
+
+ [[nodiscard]] auto elementTypes(GhostType ghost_type) const {
+ return elementTypesImpl(_all_dimensions, ghost_type, _ek_not_defined);
}
/*! 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 auto getData(GhostType ghost_type) -> DataMap &;
+ [[nodiscard]] 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 auto getData(GhostType ghost_type) const -> const DataMap &;
+ [[nodiscard]] 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 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*/
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 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 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 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 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(SupportType type, GhostType ghost_type,
- const Array<T> & vect);
+ inline void setArray(SupportType type, GhostType ghost_type, Array<T> & vect);
/*! frees all memory related to the data*/
inline void free();
inline void clear();
[[nodiscard]] inline bool empty() const;
/*! 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<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; }
+ [[nodiscard]] [[nodiscard]] inline auto getID() const -> ID {
+ return this->id;
+ }
- auto getNbComponents(Int dim = _all_dimensions,
- GhostType requested_ghost_type = _not_ghost,
- ElementKind kind = _ek_not_defined) const
- -> ElementTypeMap<Int> {
+ [[nodiscard]] 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 (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> auto size(pack &&... _pack) const -> Int;
- auto isNodal() const -> bool { return is_nodal; }
+ [[nodiscard]] auto isNodal() const -> bool { return is_nodal; }
void isNodal(bool is_nodal) { this->is_nodal = is_nodal; }
private:
- auto sizeImpl(Int spatial_dimension, GhostType ghost_type,
- ElementKind kind) const -> Int;
+ [[nodiscard]] 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>;
/// 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_tmpl.hh b/src/mesh/element_type_map_tmpl.hh
index ee4a83bda..d41679d3b 100644
--- a/src/mesh/element_type_map_tmpl.hh
+++ b/src/mesh/element_type_map_tmpl.hh
@@ -1,903 +1,880 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "integration_point.hh"
-//#include "mesh.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(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(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()(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()(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, 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;
+ << "> ["
+ << "\n";
for (auto && gt : ghost_types) {
const DataMap & data = getData(gt);
for (auto & pair : data) {
stream << space << space << ElementTypeMap::printType(pair.first, gt)
- << std::endl;
+ << "\n";
}
}
- stream << space << "]" << std::endl;
+ stream << space << "]"
+ << "\n";
}
-/* -------------------------------------------------------------------------- */
-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(
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(
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()(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()(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(
- SupportType type, GhostType ghost_type, const Array<T> & vect) {
+inline void ElementTypeMapArray<T, SupportType>::setArray(SupportType type,
+ GhostType ghost_type,
+ 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));
+ this->getData(ghost_type)[type] = &vect;
}
/* -------------------------------------------------------------------------- */
template <typename T, typename SupportType>
inline void ElementTypeMapArray<T, SupportType>::onElementsRemoved(
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_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;
+ << "> ["
+ << "\n";
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;
+ << " ["
+ << "\n";
it->second->printself(stream, indent + 3);
- stream << space << space << " ]" << std::endl;
+ stream << space << space << " ]"
+ << "\n";
}
}
- stream << space << "]" << std::endl;
+ stream << space << "]"
+ << "\n";
}
/* -------------------------------------------------------------------------- */
/* SupportType Iterator */
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
ElementTypeMap<Stored, SupportType>::type_iterator::type_iterator(
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*() {
+inline auto ElementTypeMap<Stored, SupportType>::type_iterator::operator*()
+ -> reference {
return list_begin->first;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
-inline typename ElementTypeMap<Stored, SupportType>::type_iterator::reference
-ElementTypeMap<Stored, SupportType>::type_iterator::operator*() const {
+inline auto
+ElementTypeMap<Stored, SupportType>::type_iterator::operator*() const
+ -> reference {
return list_begin->first;
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
-inline typename ElementTypeMap<Stored, SupportType>::type_iterator &
-ElementTypeMap<Stored, SupportType>::type_iterator::operator++() {
+inline auto ElementTypeMap<Stored, SupportType>::type_iterator::operator++()
+ -> type_iterator & {
++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) {
+auto ElementTypeMap<Stored, SupportType>::type_iterator::operator++(int)
+ -> type_iterator {
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();
+ -> type_iterator {
+ auto && data = container.get().getData(ghost_type);
+ auto b = data.begin();
+ auto e = data.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);
+ return type_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);
+ -> type_iterator {
+ auto && data = container.get().getData(ghost_type);
+ auto e = data.end();
+ return type_iterator(e, e, dim, kind);
}
/* -------------------------------------------------------------------------- */
template <class Stored, typename SupportType>
auto ElementTypeMap<Stored, SupportType>::elementTypesImpl(
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...);
-}
-
/* -------------------------------------------------------------------------- */
/// 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 {
+class ElementTypeMapArrayInitializer { // NOLINT
protected:
using CompFunc = std::function<Int(ElementType, GhostType)>;
public:
ElementTypeMapArrayInitializer(const CompFunc & comp_func,
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; }
+ [[nodiscard]] GhostType ghostType() const { return ghost_type; }
- virtual Int nbComponent(ElementType type) const {
+ [[nodiscard]] virtual Int nbComponent(ElementType type) const {
return comp_func(type, ghostType());
}
- virtual bool isNodal() const { return false; }
+ [[nodiscard]] virtual bool isNodal() const { return false; }
protected:
CompFunc comp_func;
Int spatial_dimension;
GhostType ghost_type;
ElementKind element_kind;
};
/* -------------------------------------------------------------------------- */
-class MeshElementTypeMapArrayInitializer
+class MeshElementTypeMapArrayInitializer // NOLINT
: public ElementTypeMapArrayInitializer {
using CompFunc = ElementTypeMapArrayInitializer::CompFunc;
public:
MeshElementTypeMapArrayInitializer(
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<Idx> * filter = nullptr)
: MeshElementTypeMapArrayInitializer(
mesh,
[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,
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<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 {
+ [[nodiscard]] 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 Idx size(ElementType type) const {
+ [[nodiscard]] 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;
}
- Int nbComponent(ElementType type) const override {
+ [[nodiscard]] 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; }
+ [[nodiscard]] 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<Idx> * filter{nullptr};
};
/* -------------------------------------------------------------------------- */
-class FEEngineElementTypeMapArrayInitializer
+class FEEngineElementTypeMapArrayInitializer // NOLINT
: public MeshElementTypeMapArrayInitializer {
public:
FEEngineElementTypeMapArrayInitializer(
const FEEngine & fe_engine, Int nb_component = 1,
Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined);
+ ElementKind element_kind = _ek_not_defined,
+ const ElementTypeMapArray<Idx> * filter = nullptr);
FEEngineElementTypeMapArrayInitializer(
const FEEngine & fe_engine,
const ElementTypeMapArrayInitializer::CompFunc & nb_component,
Int spatial_dimension = _all_dimensions,
GhostType ghost_type = _not_ghost,
- ElementKind element_kind = _ek_not_defined);
+ ElementKind element_kind = _ek_not_defined,
+ const ElementTypeMapArray<Idx> * filter = nullptr);
- Int size(ElementType type) const override;
+ [[nodiscard]] Int size(ElementType type) const override;
using ElementTypesIteratorHelper =
ElementTypeMapArray<Real, ElementType>::ElementTypesIteratorHelper;
- ElementTypesIteratorHelper elementTypes() const;
+ [[nodiscard]] auto elementTypes() const -> std::vector<ElementType>;
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 (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, Int(-2)), ghost_type,
- OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined));
+ OPTIONAL_NAMED_ARG(element_kind, _ek_not_defined),
+ OPTIONAL_NAMED_ARG(element_filter, nullptr));
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,
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,
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 {
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>
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>
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/mesh.cc b/src/mesh/mesh.cc
index a5a2a0382..5b8cc6bce 100644
--- a/src/mesh/mesh.cc
+++ b/src/mesh/mesh.cc
@@ -1,710 +1,710 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
#if defined(AKANTU_COHESIVE_ELEMENT)
#include "cohesive_element_inserter.hh"
#endif
/* -------------------------------------------------------------------------- */
#include <algorithm>
/* -------------------------------------------------------------------------- */
#include "dumper_field.hh"
#include "dumper_internal_material_field.hh"
/* -------------------------------------------------------------------------- */
#include <limits>
#include <sstream>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
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),
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(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(Int spatial_dimension, const ID & id)
: Mesh(spatial_dimension, Communicator::getStaticCommunicator(), id) {}
/* -------------------------------------------------------------------------- */
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;
/* -------------------------------------------------------------------------- */
template <>
void Mesh::sendEvent<MeshIsDistributedEvent>(MeshIsDistributedEvent & event) {
// if(event.getList().size() != 0)
EventHandlerManager<MeshEventHandler>::sendEvent(event);
}
/* -------------------------------------------------------------------------- */
template <> void Mesh::sendEvent<NewNodesEvent>(NewNodesEvent & event) {
this->computeBoundingBox();
this->nodes_flags->resize(this->nodes->size(), NodeFlag::_normal);
#if defined(AKANTU_COHESIVE_ELEMENT)
if (aka::is_of_type<CohesiveNewNodesEvent>(event)) {
// nodes might have changed in the connectivity
const auto & mesh_to_mesh_facet =
this->getData<Element>("mesh_to_mesh_facet");
for (auto ghost_type : ghost_types) {
for (auto type : connectivities.elementTypes(_spatial_dimension =
spatial_dimension - 1,
_ghost_type = ghost_type)) {
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(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 && mesh_facet_conn_it =
make_view(mesh_facets->connectivities(type, ghost_type),
nb_nodes_per_element)
.begin();
for (auto && [el, conn] : enumerate(make_view(
connectivities(type, ghost_type), nb_nodes_per_element))) {
conn = mesh_facet_conn_it[mesh_to_mesh_facet_type(el).element];
}
}
}
}
#endif
GroupManager::onNodesAdded(event.getList(), event);
EventHandlerManager<MeshEventHandler>::sendEvent(event);
}
/* -------------------------------------------------------------------------- */
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, 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);
}
[[nodiscard]] Int getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const override {
Int size = 0;
if (tag == SynchronizationTag::_smmc_facets_conn) {
Int nb_nodes = Mesh::getNbNodesPerElementList(elements);
- size += nb_nodes * sizeof(Idx);
+ size += nb_nodes * Int(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));
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, 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();
}
/* -------------------------------------------------------------------------- */
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 << "Mesh [\n";
+ stream << space << " + id : " << getID() << "\n";
stream << space << " + spatial dimension : " << this->spatial_dimension
- << std::endl;
- stream << space << " + nodes [" << std::endl;
+ << "\n";
+ stream << space << " + nodes [\n";
nodes->printself(stream, indent + 2);
- stream << space << " + connectivities [" << std::endl;
+ stream << space << " + connectivities [\n";
connectivities.printself(stream, indent + 2);
- stream << space << " ]" << std::endl;
+ stream << space << " ]\n";
GroupManager::printself(stream, indent + 1);
- stream << space << "]" << std::endl;
+ stream << space << "]\n";
}
/* -------------------------------------------------------------------------- */
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::getGlobalConnectivity(
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_view = make_view(connectivities(type, ghost_type));
auto global_conn_view = make_view(global_connectivity(type, ghost_type));
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<Int> Mesh::getNbDataPerElem(ElementTypeMapArray<T> & arrays) {
ElementTypeMap<Int> nb_data_per_elem;
for (auto type : arrays.elementTypes(_element_kind = _ek_not_defined)) {
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<Int>
Mesh::getNbDataPerElem(ElementTypeMapArray<Real> & 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;
}
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<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);
auto psize = this->communicator->getNbProc();
if (psize > 1) {
#ifdef AKANTU_USE_SCOTCH
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(AKANTU_CURRENT_FUNCTION);
this->sendEvent(event);
}
/* -------------------------------------------------------------------------- */
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 Idx & node,
Array<Element> & elements) const {
for (const auto & element : *nodes_to_elements[node]) {
elements.push_back(element);
}
}
/* -------------------------------------------------------------------------- */
void Mesh::fillNodesToElements(Int dimension) {
Element element{ElementNull};
auto nb_nodes = nodes->size();
this->nodes_to_elements.resize(nb_nodes);
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) {
element.ghost_type = ghost_type;
for (const auto & type :
elementTypes(dimension, ghost_type, _ek_not_defined)) {
element.type = type;
auto nb_element = this->getNbElement(type, ghost_type);
auto connectivity = connectivities(type, ghost_type);
auto conn_it = connectivity.begin(connectivity.getNbComponent());
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(element);
}
}
}
}
}
/* -------------------------------------------------------------------------- */
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<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 && [i, numb] : enumerate(numbering)) {
numb = i;
}
}
new_numbering(el) = -1;
}
auto find_last_not_deleted = [](auto && array, Int start) -> Int {
do {
--start;
} 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 == -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 27c0671c8..b76d89565 100644
--- a/src/mesh/mesh.hh
+++ b/src/mesh/mesh.hh
@@ -1,709 +1,720 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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()) {
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(Int spatial_dimension, const ID & id, Communicator & communicator);
public:
/// constructor that create nodes coordinates array
Mesh(Int spatial_dimension, const ID & id = "mesh");
/// mesh not distributed and not using the default 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(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<Idx> & list_1, const Array<Idx> & list_2);
/// Removes the face that the mesh is periodic
void wipePeriodicInfo();
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 Idx getPeriodicMaster(Idx slave) const;
/// get an iterable list of slaves for a given master node
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, 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 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> void 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<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<Int> & global_connectivity);
public:
void getAssociatedElements(const Array<Int> & node_list,
Array<Element> & elements);
void getAssociatedElements(const Idx & 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(Int dimension = _all_dimensions);
private:
/// update the global ids, nodes type, ...
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, 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 number of nodes
auto getNbNodes() const { return nodes->size(); }
/// get the Array of global ids of the nodes (only used in parallel)
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 auto getNodeGlobalId(Idx local_id) const;
/// get the global id of a node
inline auto getNodeLocalId(Idx global_id) const;
/// get the global number of nodes
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(Idx local_id) const;
inline auto getNodePrank(Idx local_id) const;
/// say if a node is a pure ghost node
inline bool isPureGhostNode(Idx n) const;
/// say if a node is pur local or master node
inline bool isLocalOrMasterNode(Idx n) const;
inline bool isLocalNode(Idx n) const;
inline bool isMasterNode(Idx n) const;
inline bool isSlaveNode(Idx 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, Idx);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, Idx);
AKANTU_GET_MACRO(Connectivities, connectivities,
const ElementTypeMapArray<Idx> &);
/// get the number of element of a type in the mesh
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 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,
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)
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
decltype(auto) getElementToSubelement(const Element & element) const;
/// get the subelement (element of lower dimension) connected to a element
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
decltype(auto) getSubelementToElement(const Element & element) const;
/// get connectivity of a given element
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 decltype(auto) getSubelementToElementNC(const Element & element);
/// 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 decltype(auto) getConnectivityNC(const Element & element);
public:
/// get a name field associated to the mesh
template <typename T>
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 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 decltype(auto) getData(const ID & data_name) const;
/// get a name field associated to the mesh
template <typename T> inline decltype(auto) getData(const ID & data_name);
+ template <typename T>
+ inline decltype(auto) getData(const ID & data_name, Element element) const;
+
+ template <typename T>
+ inline decltype(auto) getData(const ID & data_name, Element element);
+
template <typename T>
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 decltype(auto)
getDataPointer(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);
template <typename T>
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 auto getMeshFacets() const -> const Mesh &;
inline auto getMeshFacets() -> Mesh &;
inline auto hasMeshFacets() const { return mesh_facets != nullptr; }
/// Parent mesh accessor
inline auto getMeshParent() const -> const Mesh &;
inline auto isMeshFacets() const { return this->is_mesh_facets; }
/// return the dumper from a group and and a dumper 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 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 constexpr auto getP1ElementType(ElementType type)
-> ElementType;
/// get the kind of the element type
static inline constexpr auto getKind(ElementType type) -> ElementKind;
/// get spatial dimension of a type of element
static inline constexpr auto getSpatialDimension(ElementType type) -> Int;
/// get the natural space dimension of a type of element
static inline constexpr auto getNaturalSpaceDimension(ElementType type)
-> Int;
/// get number of facets of a given element type
static inline constexpr auto getNbFacetsPerElement(ElementType type) -> Int;
/// get number of facets of a given element type
static inline constexpr auto getNbFacetsPerElement(ElementType type, Idx t)
-> Int;
/// get local connectivity of a facet for a given facet type
static inline decltype(auto) getFacetLocalConnectivity(ElementType type,
Idx t = 0);
/// get connectivity of facets for a given element
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 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, Idx t = 0)
-> ElementType;
/// get all the type of the surface element associated to a given element
static inline decltype(auto) getAllFacetTypes(ElementType type);
/// get the number of nodes in the given element list
static inline auto getNbNodesPerElementList(const Array<Element> & elements)
-> Int;
/* ------------------------------------------------------------------------ */
/* Element type Iterator */
/* ------------------------------------------------------------------------ */
using ElementTypesIteratorHelper =
ElementTypeMapArray<Idx, ElementType>::ElementTypesIteratorHelper;
template <typename... pack>
auto elementTypes(pack &&... _pack) const -> ElementTypesIteratorHelper;
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_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_DEREF_PTR_NOT_CONST(NodesPointer, nodes);
/// get a pointer to the nodes_global_ids Array<UInt> and create it if
/// necessary
inline auto getNodesGlobalIdsPointer() -> Array<Idx> &;
/// get a pointer to the nodes_type Array<Int> and create it if necessary
inline auto getNodesFlagsPointer() -> Array<NodeFlag> &;
/// get a pointer to the connectivity Array for the given type and create it
/// if necessary
inline auto getConnectivityPointer(ElementType type,
GhostType ghost_type = _not_ghost)
-> Array<Idx> &;
/// get the ghost element counter
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 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 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<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<Idx, Int> nodes_prank;
/// global number of nodes;
Int nb_global_nodes{0};
/// all class of elements present in this mesh (for heterogenous meshes)
ElementTypeMapArray<Idx> connectivities;
/// count the references on ghost elements
ElementTypeMapArray<Idx> ghosts_counters;
/// the spatial dimension of this mesh
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<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"
+/* -------------------------------------------------------------------------- */
+#include "element_group.hh"
+#include "node_group.hh"
+/* -------------------------------------------------------------------------- */
+
#endif /* AKANTU_MESH_HH_ */
diff --git a/src/mesh/mesh_inline_impl.hh b/src/mesh/mesh_inline_impl.hh
index eccac4722..116d56918 100644
--- a/src/mesh/mesh_inline_impl.hh
+++ b/src/mesh/mesh_inline_impl.hh
@@ -1,719 +1,732 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
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>
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<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<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();
Int new_nb_nodes = 0;
for (auto new_i : new_numbering) {
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<Idx> & new_numbering) {
Array<T> tmp(vect.size(), vect.getNbComponent());
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.data() + new_i * nb_component);
++new_nb_nodes;
}
}
tmp.resize(new_nb_nodes);
vect.copy(tmp);
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::getNodesGlobalIdsPointer() -> Array<Idx> & {
AKANTU_DEBUG_IN();
if (not nodes_global_ids) {
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;
}
/* -------------------------------------------------------------------------- */
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);
}
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto) Mesh::getData(const ID & data_name,
+ Element element) const {
+ return this->getElementalData<T>(data_name)(element);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline decltype(auto) Mesh::getData(const ID & data_name, Element element) {
+ return this->getElementalData<T>(data_name)(element);
+}
+
/* -------------------------------------------------------------------------- */
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 decltype(auto)
Mesh::getElementToSubelementPointer(ElementType type, GhostType ghost_type) {
return getDataPointer<std::vector<Element>>("element_to_subelement", type,
ghost_type, 1, true);
}
/* -------------------------------------------------------------------------- */
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 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 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 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 decltype(auto)
Mesh::getSubelementToElement(const Element & element) const {
return this->getSubelementToElement().get(element);
}
/* -------------------------------------------------------------------------- */
inline decltype(auto) Mesh::getSubelementToElementNC(const Element & element) {
return this->getSubelementToElementNC().get(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 && data : enumerate(conn)) {
local_coord(std::get<0>(data)) = node_begin[std::get<1>(data)];
}
auto & barycenter = const_cast<Eigen::MatrixBase<D> &>(barycenter_);
Math::barycenter(local_coord, barycenter);
}
/* -------------------------------------------------------------------------- */
inline Vector<Real> Mesh::getBarycenter(const Element & element) const {
Vector<Real> tmp(spatial_dimension);
getBarycenter(element, tmp);
return tmp;
}
/* -------------------------------------------------------------------------- */
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 constexpr auto Element::kind() const -> ElementKind {
return Mesh::getKind(type);
}
/* -------------------------------------------------------------------------- */
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 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 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::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 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 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 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, Idx t) const
-> Matrix<Idx> {
auto local_facets = getFacetLocalConnectivity(element.type, t);
Matrix<Idx> facets(local_facets.rows(), local_facets.cols());
const auto & conn = connectivities(element.type, element.ghost_type);
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));
}
}
return facets;
}
/* -------------------------------------------------------------------------- */
inline decltype(auto) 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 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 auto Mesh::isPureGhostNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_pure_ghost;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::isLocalOrMasterNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_local_master_mask) == NodeFlag::_normal;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::isLocalNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_normal;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::isMasterNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_master;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::isSlaveNode(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_shared_mask) == NodeFlag::_slave;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::isPeriodicSlave(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_periodic_mask) ==
NodeFlag::_periodic_slave;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::isPeriodicMaster(Idx n) const -> bool {
return ((*nodes_flags)(n)&NodeFlag::_periodic_mask) ==
NodeFlag::_periodic_master;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::getNodeFlag(Idx local_id) const -> NodeFlag {
return (*nodes_flags)(local_id);
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::getNodePrank(Idx local_id) const {
auto it = nodes_prank.find(local_id);
return it == nodes_prank.end() ? -1 : it->second;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::getNodeGlobalId(Idx local_id) const {
return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id;
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::getNodeLocalId(Idx global_id) const {
if (nodes_global_ids == nullptr) {
return global_id;
}
return nodes_global_ids->find(global_id);
}
/* -------------------------------------------------------------------------- */
inline auto Mesh::getNbGlobalNodes() const {
return nodes_global_ids ? nb_global_nodes : nodes->size();
}
/* -------------------------------------------------------------------------- */
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(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);
}
/* --------------------------------------------------------------------------
*/
auto Mesh::getPeriodicMaster(Idx slave) const -> Idx {
return periodic_slave_master.at(slave);
}
/* -------------------------------------------------------------------------- */
class Mesh::PeriodicSlaves {
using internal_iterator = std::unordered_multimap<Idx, Idx>::const_iterator;
std::pair<internal_iterator, internal_iterator> pair;
public:
PeriodicSlaves(const Mesh & mesh, Idx master)
: pair(mesh.getPeriodicMasterSlaves().equal_range(master)) {}
PeriodicSlaves(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(Idx master) const {
return PeriodicSlaves(*this, master);
}
/* -------------------------------------------------------------------------- */
inline decltype(auto)
Mesh::getConnectivityWithPeriodicity(const Element & element) const {
Vector<Idx> conn = connectivities.get(element);
if (not isPeriodic()) {
return conn;
}
for (auto && node : conn) {
if (isPeriodicSlave(node)) {
node = getPeriodicMaster(node);
}
}
return conn;
}
/* -------------------------------------------------------------------------- */
inline decltype(auto) Mesh::getAssociatedElements(const Idx & node) const {
return (*nodes_to_elements[node]);
}
} // namespace akantu
diff --git a/src/mesh_utils/cohesive_element_inserter_helper.hh b/src/mesh_utils/cohesive_element_inserter_helper.hh
index 8c33a44c4..131765353 100644
--- a/src/mesh_utils/cohesive_element_inserter_helper.hh
+++ b/src/mesh_utils/cohesive_element_inserter_helper.hh
@@ -1,107 +1,107 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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);
Int insertCohesiveElement();
Int insertFacetsOnly();
private:
template <Int dim> Int insertFacetsOnlyImpl();
template <Int dim> void doubleFacets();
template <Int dim> void findSubfacetToDouble();
void doubleNodes(const std::vector<Idx> & old_nodes);
bool findElementsAroundSubfacet(
const Element & starting_element, const Element & end_facet,
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<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, Idx old_node, Idx new_node,
const std::vector<Element> & element_list,
const std::vector<Element> * facet_list = nullptr);
// update functions
void updateElementToSubelement(Int dim, bool facet_mode);
void updateSubelementToElement(Int dim, bool facet_mode);
void updateQuadraticSegments(Int dim);
void updateCohesiveData();
void doublePointFacet();
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<Idx> doubled_nodes;
Array<Element> new_elements;
Mesh & mesh;
Mesh & mesh_facets;
ElementTypeMap<Int> nb_new_facets;
};
} // namespace akantu
-#endif /* __AKANTU_COHESIVE_ELEMENT_INSERTER_HELPER_HH__ */
+#endif /* AKANTU_COHESIVE_ELEMENT_INSERTER_HELPER_HH_ */
diff --git a/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc b/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc
index 0de0d3bce..d16a1d5c1 100644
--- a/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc
+++ b/src/mesh_utils/mesh_partition/mesh_partition_scotch.cc
@@ -1,448 +1,447 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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");
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();
auto spatial_dimension = mesh.getSpatialDimension();
auto nb_nodes = mesh.getNbNodes();
Int total_nb_element = 0;
Int nb_edge = 0;
for (const auto & type : mesh.elementTypes(spatial_dimension)) {
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;
}
const auto & connectivity = mesh.getConnectivity(type, _not_ghost);
/// count number of occurrence of each node
for (auto && conn : make_view(connectivity, connectivity.getNbComponent()))
for (auto && node : conn)
verttab[node]++;
}
/// convert the occurrence array in a csr one
for (Int i = 1; i < nb_nodes; ++i) {
verttab[i] += verttab[i - 1];
}
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];
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 (Int i = nb_nodes; i > 0; --i) {
verttab[i] = verttab[i - 1];
}
verttab[0] = 0;
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();
const Real * nodes_val = nodes.data();
for (Int i = 0; i < nb_nodes; ++i) {
fgeominit << i << " ";
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(
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.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.data(); // integer load associated with
// every edge ( optional )
SCOTCH_Num * edgetab = dadjncy.data(); // adjacency array of every vertex
SCOTCH_Num * vlbltab = nullptr; // vertex label array (optional)
/// Allocate space for Scotch arrays
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 auto & nodes = mesh.getNodes();
auto nodes_it = nodes.begin(spatial_dimension);
Int out_linerized_el = 0;
for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_not_defined)) {
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 += nodes_it[node];
}
mid /= conn.size();
fgeominit << out_linerized_el++ << " ";
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);
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);
auto nb_nodes = mesh.getNbNodes();
SCOTCH_Strat scotch_strat;
// SCOTCH_Ordering scotch_order;
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.data(), peritab,
&cblknbr, rangtab, treetab);
SCOTCH_graphExit(&scotch_graph);
SCOTCH_stratExit(&scotch_strat);
destroyMesh(scotch_mesh);
/// Renumbering
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
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);
}
mesh_accessor.getNodes().copy(new_coordinates);
AKANTU_DEBUG_OUT();
}
} // namespace akantu
diff --git a/src/mesh_utils/mesh_utils_distribution.cc b/src/mesh_utils/mesh_utils_distribution.cc
index 85503272d..c24e31d15 100644
--- a/src/mesh_utils/mesh_utils_distribution.cc
+++ b/src/mesh_utils/mesh_utils_distribution.cc
@@ -1,151 +1,152 @@
/**
* Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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*/,
+ void distributeMeshCentralized(Mesh & mesh, Int /*unused*/,
const MeshPartition & partition) {
MeshAccessor mesh_accessor(mesh);
auto & element_synchronizer = mesh_accessor.getElementSynchronizer();
auto & node_synchronizer = mesh_accessor.getNodeSynchronizer();
const auto & comm = element_synchronizer.getCommunicator();
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;
+ Int 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);
+ auto && partiton [[maybe_unused]] =
+ 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) {
+ void distributeMeshCentralized(Mesh & mesh, Int root) {
MeshAccessor mesh_accessor(mesh);
auto & element_synchronizer = mesh_accessor.getElementSynchronizer();
auto & node_synchronizer = mesh_accessor.getNodeSynchronizer();
const auto & comm = element_synchronizer.getCommunicator();
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;
+ Int 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_distribution.hh b/src/mesh_utils/mesh_utils_distribution.hh
index 8f5e2edec..8fee2c1cb 100644
--- a/src/mesh_utils/mesh_utils_distribution.hh
+++ b/src/mesh_utils/mesh_utils_distribution.hh
@@ -1,45 +1,45 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_MESH_UTILS_DISTRIBUTION_HH_
#define AKANTU_MESH_UTILS_DISTRIBUTION_HH_
namespace akantu {
class Mesh;
class MeshPartition;
} // namespace akantu
namespace akantu {
namespace MeshUtilsDistribution {
/// Master call to distribute a mesh in a centralized manner (the UInt is just
/// to avoid some shitty access from the slave...)
- void distributeMeshCentralized(Mesh & mesh, UInt /*unused*/,
+ void distributeMeshCentralized(Mesh & mesh, Int /*unused*/,
const MeshPartition & partition);
/// Slave call to distribute a mesh in a centralized manner
- void distributeMeshCentralized(Mesh & mesh, UInt root);
+ void distributeMeshCentralized(Mesh & mesh, Int root);
} // namespace MeshUtilsDistribution
} // namespace akantu
#endif /* AKANTU_MESH_UTILS_DISTRIBUTION_HH_ */
diff --git a/src/model/common/constitutive_laws/constitutive_law.hh b/src/model/common/constitutive_laws/constitutive_law.hh
new file mode 100644
index 000000000..4d55af04d
--- /dev/null
+++ b/src/model/common/constitutive_laws/constitutive_law.hh
@@ -0,0 +1,349 @@
+/**
+ * @file constitutive_law.hh
+ *
+ * @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: Wed Feb 21 2018
+ *
+ * @brief Mother class for all constitutive laws
+ *
+ *
+ * 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 "data_accessor.hh"
+#include "mesh_events.hh"
+#include "parsable.hh"
+#include "parser.hh"
+/* -------------------------------------------------------------------------- */
+#include "internal_field.hh"
+#include "random_internal_field.hh"
+/* -------------------------------------------------------------------------- */
+
+namespace akantu {
+class FEEngine;
+}
+
+#ifndef AKANTU_CONSTITUTIVE_LAW_HH_
+#define AKANTU_CONSTITUTIVE_LAW_HH_
+
+/* -------------------------------------------------------------------------- */
+namespace akantu {
+
+class ConstitutiveLawInternalHandler {
+public:
+ ConstitutiveLawInternalHandler(const ID & id, Int dim,
+ const ID & fe_engine_id)
+ : id(id), spatial_dimension(dim), default_fe_engine_id(fe_engine_id) {
+ this->element_filter =
+ std::make_shared<ElementTypeMapArray<Idx>>("element_filter", id);
+ }
+
+ virtual ~ConstitutiveLawInternalHandler() = default;
+
+ ConstitutiveLawInternalHandler(ConstitutiveLawInternalHandler &&) noexcept =
+ delete;
+ ConstitutiveLawInternalHandler(const ConstitutiveLawInternalHandler &) =
+ delete;
+
+ ConstitutiveLawInternalHandler &
+ operator=(ConstitutiveLawInternalHandler &&) noexcept = delete;
+ ConstitutiveLawInternalHandler &
+ operator=(const ConstitutiveLawInternalHandler &) = delete;
+
+ template <typename T = Real,
+ template <typename Type> class InternalFieldType = InternalField>
+ inline InternalFieldType<T> & registerInternal(const ID & id,
+ Int nb_component);
+
+ template <typename T = Real,
+ template <typename Type> class InternalFieldType = InternalField>
+ inline InternalFieldType<T> &
+ registerInternal(const ID & id, Int nb_component, const ID & fe_engine_id);
+
+ template <typename T = Real,
+ template <typename Type> class InternalFieldType = InternalField>
+ inline InternalFieldType<T> &
+ registerInternal(const ID & id, Int nb_component, const ID & fe_engine_id,
+ const ElementTypeMapArray<Idx> & element_filter);
+
+ inline void unregisterInternal(const ID & id);
+
+ /// resize the internals arrrays
+ virtual void resizeInternals();
+
+public:
+ /// save the internals in the previous_state if needed
+ virtual void savePreviousState();
+
+ /// restore the internals from previous_state if needed
+ virtual void restorePreviousState();
+
+ template <typename T = Real>
+ const InternalField<T> & getInternal(const ID & id) const;
+
+ template <typename T> InternalField<T> & getInternal(const ID & id);
+
+ template <typename T = Real,
+ template <typename Type> class InternalFieldType = InternalField>
+ std::shared_ptr<InternalFieldType<T>> getSharedPtrInternal(const ID & id);
+
+ template <typename T>
+ [[nodiscard]] inline bool isInternal(const ID & id,
+ const ElementKind & element_kind) const;
+
+ 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);
+
+ inline void removeIntegrationPoints(ElementTypeMapArray<Idx> & new_numbering);
+
+public:
+ [[nodiscard]] virtual const FEEngine &
+ getFEEngine(const ID & /*id*/ = "") const {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ [[nodiscard]] virtual FEEngine & getFEEngine(const ID & /*id*/ = "") {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ [[nodiscard]] Int getSpatialDimension() const { return spatial_dimension; }
+
+ [[nodiscard]] const ElementTypeMapArray<Idx> & getElementFilter() const {
+ return *element_filter;
+ }
+
+ [[nodiscard]] std::shared_ptr<const ElementTypeMapArray<Idx>>
+ getElementFilterSharedPtr() const {
+ return element_filter;
+ }
+
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, (*element_filter), Idx);
+
+ AKANTU_GET_MACRO(Name, name, const std::string &);
+ AKANTU_GET_MACRO(ID, id, const ID &);
+
+protected:
+ [[nodiscard]] ElementTypeMapArray<Idx> & getElementFilter() {
+ return *element_filter;
+ }
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementFilter, (*element_filter), Idx);
+
+private:
+ std::map<ID, std::shared_ptr<InternalFieldBase>> internal_vectors;
+
+ /// list of element handled by the constitutive law
+ std::shared_ptr<ElementTypeMapArray<Idx>> element_filter;
+
+protected:
+ ID id;
+
+ // spatial dimension for constitutive law
+ Int spatial_dimension{0};
+
+ /// constitutive law name
+ std::string name;
+
+ /// ID of the FEEngine containing the interpolation points that are the
+ /// support of the internal fields
+ ID default_fe_engine_id;
+};
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+class ConstitutiveLaw : public ConstitutiveLawInternalHandler,
+ public DataAccessor<Element>,
+ public MeshEventHandler,
+ public Parsable {
+
+ /* ------------------------------------------------------------------------ */
+ /* Constructors/Destructors */
+ /* ------------------------------------------------------------------------ */
+public:
+ using ConstitutiveLawsHandler = ConstitutiveLawsHandler_;
+
+ /// Initialize constitutive law with defaults
+ ConstitutiveLaw(ConstitutiveLawsHandler & handler, const ID & id = "",
+ Int spatial_dimension = _all_dimensions,
+ ElementKind element_kind = _ek_regular,
+ const ID & fe_engine_id = "");
+
+ void printself(std::ostream & stream, int indent = 0) const override {
+ std::string space(indent, AKANTU_INDENT);
+ std::cout << "Constitutive Law [\n";
+ stream << space << " + id : " << id << "\n";
+ stream << space << " + name : " << name << "\n";
+ stream << space << " + spatial dimension : " << spatial_dimension << "\n";
+ stream << space << " + default FE Engine : " << default_fe_engine_id
+ << "\n";
+ Parsable::printself(stream, indent + 1);
+ stream << space << "]\n";
+ }
+
+protected:
+ void initialize();
+
+ /* ------------------------------------------------------------------------ */
+ /* Methods */
+ /* ------------------------------------------------------------------------ */
+public:
+ /// initialize the constitutive law computed parameter
+ virtual void initConstitutiveLaw();
+
+ /// add an element to the local mesh filter
+ inline Idx 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);
+
+ [[nodiscard]] virtual Real getEnergy(const ID & /*energy_id*/) { return 0; }
+ [[nodiscard]] virtual Real getEnergy(const ID & /*energy_id*/,
+ const Element & /*element*/) {
+ return 0;
+ }
+
+protected:
+ /// function called to update the internal parameters when the
+ /// modifiable parameters are modified
+ virtual void updateInternalParameters() {}
+
+ /// converts global element to local element
+ [[nodiscard]] inline Element
+ convertToLocalElement(const Element & global_element) const;
+ /// converts local element to global element
+ [[nodiscard]] inline Element
+ convertToGlobalElement(const Element & local_element) const;
+
+ /* ------------------------------------------------------------------------ */
+ /* DataAccessor inherited members */
+ /* ------------------------------------------------------------------------ */
+public:
+ template <typename T>
+ inline void packInternalFieldHelper(const InternalField<T> & data_to_pack,
+ CommunicationBuffer & buffer,
+ const Array<Element> & elements) const;
+
+ template <typename T>
+ inline void unpackInternalFieldHelper(InternalField<T> & data_to_unpack,
+ CommunicationBuffer & buffer,
+ const Array<Element> & elements);
+
+ /* ------------------------------------------------------------------------ */
+ /* MeshEventHandler inherited members */
+ /* ------------------------------------------------------------------------ */
+public:
+ /* ------------------------------------------------------------------------ */
+ void onNodesAdded(const Array<Idx> & /*unused*/,
+ const NewNodesEvent & /*unused*/) override{};
+ void onNodesRemoved(const Array<Idx> & /*unused*/,
+ const Array<Idx> & /*unused*/,
+ const RemovedNodesEvent & /*unused*/) override{};
+
+ void onElementsChanged(const Array<Element> & /*unused*/,
+ const Array<Element> & /*unused*/,
+ const ElementTypeMapArray<Idx> & /*unused*/,
+ const ChangedElementsEvent & /*unused*/) override{};
+
+ void onElementsAdded(const Array<Element> & /*unused*/,
+ const NewElementsEvent & /*unused*/) override;
+
+ void onElementsRemoved(const Array<Element> & element_list,
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & event) override;
+
+public:
+ template <typename T> inline void setParam(const ID & param, T value);
+ [[nodiscard]] 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, ElementKind element_kind);
+
+ /* ------------------------------------------------------------------------ */
+ /* Accessors */
+ /* ------------------------------------------------------------------------ */
+public:
+ [[nodiscard]] const FEEngine &
+ getFEEngine(const ID & id = "") const override {
+ return handler.getFEEngine(id.empty() ? default_fe_engine_id : id);
+ }
+
+ [[nodiscard]] FEEngine & getFEEngine(const ID & id = "") override {
+ return handler.getFEEngine(id.empty() ? default_fe_engine_id : id);
+ }
+
+ template <typename T>
+ [[nodiscard]] ElementTypeMap<Int>
+ getInternalDataPerElem(const ID & id, ElementKind element_kind) const;
+
+ AKANTU_GET_MACRO_AUTO(Handler, handler);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Handler, handler);
+
+ template <typename... pack>
+ decltype(auto) elementTypes(pack &&... _pack) const {
+ return this->getElementFilter().elementTypes(std::forward<pack>(_pack)...);
+ }
+
+protected:
+ [[nodiscard]] bool isInit() const { return is_init; }
+
+ /* ------------------------------------------------------------------------ */
+ /* Class Members */
+ /* ------------------------------------------------------------------------ */
+private:
+ /// boolean to know if the constitutive law has been initialized
+ bool is_init{false};
+
+protected:
+ // Constitutive law handler for which this is a constitutive law
+ ConstitutiveLawsHandler & handler;
+};
+
+template <class ConstitutiveLawsHandler_>
+inline std::ostream &
+operator<<(std::ostream & stream,
+ const ConstitutiveLaw<ConstitutiveLawsHandler_> & _this) {
+ _this.printself(stream);
+ return stream;
+}
+
+} // namespace akantu
+
+#include "constitutive_law_tmpl.hh"
+#include "internal_field_tmpl.hh"
+#include "random_internal_field_tmpl.hh"
+
+#endif
diff --git a/src/model/solid_mechanics/materials/material_non_local.hh b/src/model/common/constitutive_laws/constitutive_law_non_local_interface.hh
similarity index 63%
copy from src/model/solid_mechanics/materials/material_non_local.hh
copy to src/model/common/constitutive_laws/constitutive_law_non_local_interface.hh
index 6778a70bd..23a459a8b 100644
--- a/src/model/solid_mechanics/materials/material_non_local.hh
+++ b/src/model/common/constitutive_laws/constitutive_law_non_local_interface.hh
@@ -1,106 +1,120 @@
/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ * @file constitutive_law_non_local.hh
+ *
+ * @author Aurelia Isabel Cuba Ramos <aurelia.cubaramos@epfl.ch>
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
*
- * This file is part of Akantu
+ * @date creation: Fri Jun 18 2010
+ * @date last modification: Mon Sep 11 2017
*
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
+ * @brief ConstitutiveLaw class that handle the non locality of a law for
+ * example damage.
+ *
+ * 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
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
- * You should have received a copy of the GNU Lesser General Public License
+ * You 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 "constitutive_law.hh"
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_MATERIAL_NON_LOCAL_HH_
-#define AKANTU_MATERIAL_NON_LOCAL_HH_
+#ifndef AKANTU_CONSTITUTIVE_LAW_NON_LOCAL_HH_
+#define AKANTU_CONSTITUTIVE_LAW_NON_LOCAL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-class MaterialNonLocalInterface {
+class ConstitutiveLawNonLocalInterface {
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- /// initialize the material the non local parts of the material
- void initMaterialNonLocal() {
+ /// initialize the constitutive_law the non local parts of the
+ /// constitutive_law
+ void initConstitutiveLawNonLocal() {
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
+ /// get the name of the neighborhood for this constitutive_law
virtual ID getNeighborhoodName() = 0;
- /// register the neighborhoods for the material
+ /// register the neighborhoods for the constitutive_law
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 <Int dim, class LocalParent>
-class MaterialNonLocal : public MaterialNonLocalInterface, public LocalParent {
+template <Int dim, class ConstitutiveLawNonLocalInterface,
+ class ConstitutiveLawParent>
+class ConstitutiveLawNonLocal : public ConstitutiveLawNonLocalInterface,
+ public ConstitutiveLawParent {
+
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- explicit MaterialNonLocal(SolidMechanicsModel & model, const ID & id);
+ explicit ConstitutiveLawNonLocal(
+ typename ConstitutiveLawParent::ConstitutiveLawsHandler & handler,
+ 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
+ /// register the neighborhoods for the constitutive_law
void registerNeighborhood() override;
protected:
- /// get the name of the neighborhood for this material
+ /// get the name of the neighborhood for this constitutive_law
ID getNeighborhoodName() override { return this->name; }
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
-#include "material_non_local_tmpl.hh"
+#include "constitutive_law_non_local_interface_tmpl.hh"
-#endif /* AKANTU_MATERIAL_NON_LOCAL_HH_ */
+#endif /* AKANTU_CONSTITUTIVE_LAW_NON_LOCAL_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh b/src/model/common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh
similarity index 61%
rename from src/model/solid_mechanics/materials/material_non_local_tmpl.hh
rename to src/model/common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh
index 9b04c6c41..feab94785 100644
--- a/src/model/solid_mechanics/materials/material_non_local_tmpl.hh
+++ b/src/model/common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh
@@ -1,117 +1,124 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "constitutive_law_non_local_interface.hh"
#include "non_local_neighborhood.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-template <Int dim, class LocalParent>
-MaterialNonLocal<dim, LocalParent>::MaterialNonLocal(
- SolidMechanicsModel & model, const ID & id)
- : LocalParent(model, id) {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
-}
+template <Int dim, class ConstitutiveLawNonLocalInterface,
+ class ConstitutiveLawParent>
+ConstitutiveLawNonLocal<dim, ConstitutiveLawNonLocalInterface,
+ ConstitutiveLawParent>::
+ ConstitutiveLawNonLocal(
+ typename ConstitutiveLawParent::ConstitutiveLawsHandler & handler,
+ const ID & id)
+ : ConstitutiveLawParent(handler, id) {}
/* -------------------------------------------------------------------------- */
-template <Int dim, class LocalParent>
-void MaterialNonLocal<dim, LocalParent>::insertIntegrationPointsInNeighborhoods(
- GhostType ghost_type,
- const ElementTypeMapReal & quadrature_points_coordinates) {
+template <Int dim, class ConstitutiveLawNonLocalInterface,
+ class ConstitutiveLawParent>
+void ConstitutiveLawNonLocal<dim, ConstitutiveLawNonLocalInterface,
+ ConstitutiveLawParent>::
+ insertIntegrationPointsInNeighborhoods(
+ GhostType ghost_type,
+ const ElementTypeMapReal & quadrature_points_coordinates) {
IntegrationPoint q;
q.ghost_type = ghost_type;
- auto & neighborhood = this->model.getNonLocalManager().getNeighborhood(
+ auto & neighborhood = this->getModel().getNonLocalManager().getNeighborhood(
this->getNeighborhoodName());
for (auto && type :
- this->element_filter.elementTypes(dim, ghost_type, _ek_regular)) {
+ this->getElementFilter().elementTypes(dim, ghost_type, _ek_regular)) {
q.type = type;
- const auto & elem_filter = this->element_filter(type, ghost_type);
+ const auto & elem_filter = this->getElementFilter(type, ghost_type);
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 <Int dim, class LocalParent>
-void MaterialNonLocal<dim, LocalParent>::updateNonLocalInternals(
- ElementTypeMapReal & non_local_flattened, const ID & field_id,
- GhostType ghost_type, ElementKind kind) {
+template <Int dim, class ConstitutiveLawNonLocalInterface,
+ class ConstitutiveLawParent>
+void ConstitutiveLawNonLocal<dim, ConstitutiveLawNonLocalInterface,
+ ConstitutiveLawParent>::
+ 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 :
- this->element_filter.elementTypes(dim, ghost_type, kind)) {
+ this->getElementFilter().elementTypes(dim, ghost_type, kind)) {
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);
+ const auto & filter = this->getElementFilter(el_type, ghost_type);
Int nb_quads =
this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type);
for (auto & elem : filter) {
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 <Int dim, class LocalParent>
-void MaterialNonLocal<dim, LocalParent>::registerNeighborhood() {
+template <Int dim, class ConstitutiveLawNonLocalInterface,
+ class ConstitutiveLawParent>
+void ConstitutiveLawNonLocal<dim, ConstitutiveLawNonLocalInterface,
+ ConstitutiveLawParent>::registerNeighborhood() {
ID name = this->getNeighborhoodName();
- this->model.getNonLocalManager().registerNeighborhood(name, name);
+ this->handler.getNonLocalManager().registerNeighborhood(name, name);
}
} // namespace akantu
diff --git a/src/model/common/constitutive_laws/constitutive_law_selector.hh b/src/model/common/constitutive_laws/constitutive_law_selector.hh
new file mode 100644
index 000000000..430779c66
--- /dev/null
+++ b/src/model/common/constitutive_laws/constitutive_law_selector.hh
@@ -0,0 +1,156 @@
+/**
+ * @file constitutive_law_selector.hh
+ *
+ * @author Nicolas Richart
+ *
+ * @date creation ven mar 26 2021
+ *
+ * @brief class to dispatch cl to elements
+ *
+ * @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 "mesh.hh"
+/* -------------------------------------------------------------------------- */
+#include <memory>
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_CONSTITUTIVE_LAW_SELECTOR_HH
+#define AKANTU_CONSTITUTIVE_LAW_SELECTOR_HH
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+/**
+ * main class to assign same or different constitutive_laws for different
+ * elements
+ */
+class ConstitutiveLawSelector
+ : public std::enable_shared_from_this<ConstitutiveLawSelector> {
+public:
+ ConstitutiveLawSelector() = default;
+
+ ConstitutiveLawSelector(const ConstitutiveLawSelector &) = default;
+ ConstitutiveLawSelector(ConstitutiveLawSelector &&) noexcept = default;
+
+ ConstitutiveLawSelector &
+ operator=(const ConstitutiveLawSelector &) = default;
+ ConstitutiveLawSelector &
+ operator=(ConstitutiveLawSelector &&) noexcept = default;
+
+ virtual ~ConstitutiveLawSelector() = default;
+ virtual inline Idx operator()(const Element & element) {
+ if (fallback_selector) {
+ return (*fallback_selector)(element);
+ }
+
+ return fallback_value;
+ }
+
+ inline void setFallback(Idx f) { fallback_value = f; }
+ inline void setFallback(
+ const std::shared_ptr<ConstitutiveLawSelector> & fallback_selector) {
+ this->fallback_selector = fallback_selector;
+ }
+
+ inline void setFallback(ConstitutiveLawSelector & fallback_selector) {
+ this->fallback_selector = fallback_selector.shared_from_this();
+ }
+
+ inline std::shared_ptr<ConstitutiveLawSelector> & getFallbackSelector() {
+ return this->fallback_selector;
+ }
+
+ inline Idx getFallbackValue() const { return this->fallback_value; }
+
+private:
+ Idx fallback_value{0};
+ std::shared_ptr<ConstitutiveLawSelector> fallback_selector;
+};
+
+/* -------------------------------------------------------------------------- */
+/**
+ * class that assigns the first constitutive_law to regular elements by default
+ */
+class DefaultConstitutiveLawSelector : public ConstitutiveLawSelector {
+public:
+ explicit DefaultConstitutiveLawSelector(
+ const ElementTypeMapArray<Idx> & constitutive_law_index)
+ : constitutive_law_index(constitutive_law_index) {}
+
+ Int operator()(const Element & element) override {
+ if (not constitutive_law_index.exists(element.type, element.ghost_type)) {
+ return ConstitutiveLawSelector::operator()(element);
+ }
+
+ const auto & mat_indexes =
+ constitutive_law_index(element.type, element.ghost_type);
+ if (element.element < mat_indexes.size()) {
+ auto && tmp_mat = mat_indexes(element.element);
+ if (tmp_mat != -1) {
+ return tmp_mat;
+ }
+ }
+
+ return ConstitutiveLawSelector::operator()(element);
+ }
+
+private:
+ const ElementTypeMapArray<Idx> & constitutive_law_index;
+};
+
+template <typename T, class Model_>
+class ElementDataConstitutiveLawSelector : public ConstitutiveLawSelector {
+public:
+ ElementDataConstitutiveLawSelector(
+ const ElementTypeMapArray<T> & element_data, const Model_ & model,
+ Idx first_index = 1)
+ : element_data(element_data), model(model), first_index(first_index) {}
+ inline Idx operator()(const Element & element) override;
+
+private:
+ inline T elementData(const Element & element) {
+ debug::DebugLevelContext ctxt(dblError);
+ return element_data(element);
+ }
+
+ /// list of element with the specified data (i.e. tag value)
+ const ElementTypeMapArray<T> & element_data;
+
+ /// the model that the materials belong
+ const Model_ & model;
+
+ /// first constitutive_law index: equal to 1 if none specified
+ Int first_index;
+};
+
+template <typename T, class Model_>
+class MeshDataConstitutiveLawSelector
+ : public ElementDataConstitutiveLawSelector<T, Model_> {
+public:
+ MeshDataConstitutiveLawSelector(const std::string & name,
+ const Model_ & model, Idx first_index = 1);
+};
+
+} // namespace akantu
+
+#include "constitutive_law_selector_tmpl.hh"
+
+#endif /* AKANTU_CONSTITUTIVE_LAW_SELECTOR_HH */
diff --git a/src/model/common/constitutive_laws/constitutive_law_selector_tmpl.hh b/src/model/common/constitutive_laws/constitutive_law_selector_tmpl.hh
new file mode 100644
index 000000000..8343c990f
--- /dev/null
+++ b/src/model/common/constitutive_laws/constitutive_law_selector_tmpl.hh
@@ -0,0 +1,31 @@
+#ifndef AKANTU_CONSTITUTIVE_LAW_SELECTOR_TMPL_HH_
+#define AKANTU_CONSTITUTIVE_LAW_SELECTOR_TMPL_HH_
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <typename T, class Model_>
+inline Idx ElementDataConstitutiveLawSelector<T, Model_>::operator()(
+ const Element & element) {
+ try {
+ auto && data = this->elementData(element);
+ if constexpr (std::is_same_v<T, std::string>) {
+ return this->model.getConstitutiveLawIndex(data);
+ } else {
+ return data;
+ }
+ } catch (...) {
+ return ConstitutiveLawSelector::operator()(element);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, class Model_>
+MeshDataConstitutiveLawSelector<T, Model_>::MeshDataConstitutiveLawSelector(
+ const std::string & name, const Model_ & model, Idx first_index)
+ : ElementDataConstitutiveLawSelector<T, Model_>(
+ model.getMesh().template getData<T>(name), model, first_index) {}
+
+} // namespace akantu
+
+#endif // AKANTU_CONSTITUTIVE_LAW_SELECTOR_TMPL_HH_
diff --git a/src/model/common/constitutive_laws/constitutive_law_tmpl.hh b/src/model/common/constitutive_laws/constitutive_law_tmpl.hh
new file mode 100644
index 000000000..0d4056d4c
--- /dev/null
+++ b/src/model/common/constitutive_laws/constitutive_law_tmpl.hh
@@ -0,0 +1,625 @@
+/**
+ * @file constitutive_law_tmpl.hh *
+ * @author Guillaume Anciaux <guillaume.anciaux@epfl.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>
+ * @author Marco Vocialta <marco.vocialta@epfl.ch>
+ *
+ * @date creation: Tue Jul 27 2010
+ * @date last modification: Wed Feb 21 2018
+ *
+ * @brief Implementation of the templated part of the constitutive law class
+ *
+ *
+ * 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 "constitutive_law.hh" // NOLINT
+#include "constitutive_laws_handler.hh"
+#include "fe_engine.hh"
+#include "internal_field.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_CONSTITUTIVE_LAW_TMPL_HH
+#define AKANTU_CONSTITUTIVE_LAW_TMPL_HH
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <typename T, template <typename Type> class InternalFieldType>
+inline InternalFieldType<T> &
+ConstitutiveLawInternalHandler::registerInternal(const ID & id,
+ Int nb_component) {
+ return this->registerInternal<T, InternalFieldType>(
+ id, nb_component, this->default_fe_engine_id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, template <typename Type> class InternalFieldType>
+inline InternalFieldType<T> & ConstitutiveLawInternalHandler::registerInternal(
+ const ID & id, Int nb_component, const ID & fe_engine_id) {
+ return this->registerInternal<T, InternalFieldType>(
+ id, nb_component, fe_engine_id, this->getElementFilter());
+}
+/* -------------------------------------------------------------------------- */
+template <typename T, template <typename Type> class InternalFieldType>
+inline InternalFieldType<T> & ConstitutiveLawInternalHandler::registerInternal(
+ const ID & id, Int nb_component, const ID & fe_engine_id,
+ const ElementTypeMapArray<Idx> & element_filter) {
+ auto && internal =
+ std::shared_ptr<InternalFieldType<T>>(new InternalFieldType<T>(
+ id, *this, this->spatial_dimension, fe_engine_id, element_filter));
+ internal->initialize(nb_component);
+ internal_vectors[internal->getRegisterID()] = internal;
+ return *internal;
+}
+
+/* -------------------------------------------------------------------------- */
+inline void ConstitutiveLawInternalHandler::unregisterInternal(const ID & id) {
+ internal_vectors.erase(id);
+}
+
+/* -------------------------------------------------------------------------- */
+inline void ConstitutiveLawInternalHandler::savePreviousState() {
+ for (auto && [_, internal] : internal_vectors) {
+ if (internal->hasHistory()) {
+ internal->saveCurrentValues();
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+inline void ConstitutiveLawInternalHandler::restorePreviousState() {
+ for (auto && [_, internal] : internal_vectors) {
+ if (internal->hasHistory()) {
+ internal->restorePreviousValues();
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+inline void ConstitutiveLawInternalHandler::resizeInternals() {
+ for (auto && [_, internal] : internal_vectors) {
+ internal->resize();
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+const InternalField<T> &
+ConstitutiveLawInternalHandler::getInternal(const ID & id) const {
+ auto it = internal_vectors.find(id);
+ if (it != internal_vectors.end() and
+ aka::is_of_type<InternalField<T>>(*it->second)) {
+ return aka::as_type<InternalField<T>>(*it->second);
+ }
+
+ AKANTU_SILENT_EXCEPTION("The constitutive law "
+ << name << "(" << getID()
+ << ") does not contain an internal " << id << " ("
+ << (getID() + ":" + id) << ")");
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+InternalField<T> & ConstitutiveLawInternalHandler::getInternal(const ID & id) {
+ if (auto it = internal_vectors.find(id);
+ it != internal_vectors.end() and
+ aka::is_of_type<InternalField<T>>(*it->second)) {
+ return aka::as_type<InternalField<T>>(*it->second);
+ }
+
+ AKANTU_SILENT_EXCEPTION("The constitutive law "
+ << name << "(" << getID()
+ << ") does not contain an internal " << id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, template <typename Type> class InternalFieldType>
+std::shared_ptr<InternalFieldType<T>>
+ConstitutiveLawInternalHandler::getSharedPtrInternal(const ID & id) {
+ if (auto it = this->internal_vectors.find(id);
+ it != internal_vectors.end() and
+ aka::is_of_type<InternalFieldType<T>>(*it->second)) {
+ return std::dynamic_pointer_cast<InternalFieldType<T>>(it->second);
+ }
+
+ AKANTU_SILENT_EXCEPTION("The constitutive law "
+ << name << "(" << getID()
+ << ") does not contain an internal " << id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+inline bool ConstitutiveLawInternalHandler::isInternal(
+ const ID & id, const ElementKind & element_kind) const {
+ auto it = internal_vectors.find(id);
+
+ return ((it != internal_vectors.end()) and
+ aka::is_of_type<InternalField<T>>(*it->second) and
+ aka::as_type<InternalField<T>>(*it->second).getElementKind() ==
+ element_kind);
+}
+
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+template <typename T>
+const Array<T> &
+ConstitutiveLawInternalHandler::getArray(const ID & vect_id, ElementType type,
+ GhostType ghost_type) const {
+ if (isInternal<T>(vect_id, Mesh::getKind(type))) {
+ auto && internal = this->template getInternal<T>(vect_id);
+ if (internal.exists(type, ghost_type)) {
+ return internal(type, ghost_type);
+ }
+
+ AKANTU_SILENT_EXCEPTION(
+ "The internal " << vect_id << " in the constitutive law " << name
+ << " (" << getID() << ") does not contain the type ["
+ << type << ":" << ghost_type << "]");
+ }
+
+ AKANTU_SILENT_EXCEPTION("The constitutive law "
+ << name << " (" << getID()
+ << ") does not contain an internal field "
+ << vect_id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T>
+Array<T> & ConstitutiveLawInternalHandler::getArray(const ID & vect_id,
+ ElementType type,
+ GhostType ghost_type) {
+ if (isInternal<T>(vect_id, Mesh::getKind(type))) {
+ auto && internal = this->template getInternal<T>(vect_id);
+ if (internal.exists(type, ghost_type)) {
+ return internal(type, ghost_type);
+ }
+ AKANTU_SILENT_EXCEPTION(
+ "The internal " << vect_id << " in the constitutive law " << name
+ << " (" << getID() << ") does not contain the type ["
+ << type << ":" << ghost_type << "]");
+ }
+
+ AKANTU_SILENT_EXCEPTION("The constitutive law "
+ << name << " (" << getID()
+ << ") does not contain an internal field "
+ << vect_id);
+}
+
+/* -------------------------------------------------------------------------- */
+inline void ConstitutiveLawInternalHandler::removeIntegrationPoints(
+ ElementTypeMapArray<Idx> & new_numbering) {
+ for (auto && [_, internal] : internal_vectors) {
+ internal->removeIntegrationPoints(new_numbering);
+ }
+}
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+ConstitutiveLaw<ConstitutiveLawsHandler_>::ConstitutiveLaw(
+ ConstitutiveLawsHandler_ & handler, const ID & id, Int spatial_dimension,
+ ElementKind element_kind, const ID & fe_engine_id)
+ : ConstitutiveLawInternalHandler(id, spatial_dimension, fe_engine_id),
+ Parsable(handler.getConstitutiveLawParserType(), id), handler(handler) {
+
+ /// for each connectivity types allocate the element filer array of
+ /// the constitutive law
+ this->getElementFilter().initialize(
+ handler.getMesh(), _spatial_dimension = handler.getSpatialDimension(),
+ _element_kind = element_kind);
+
+ this->initialize();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::initialize() {
+ registerParam("name", name, std::string(), _pat_parsable | _pat_readable);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::initConstitutiveLaw() {
+ this->resizeInternals();
+ this->updateInternalParameters();
+ is_init = true;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::addElements(
+ const Array<Element> & elements_to_add) {
+ AKANTU_DEBUG_IN();
+
+ Int law_id = handler.getConstitutiveLawIndex(name);
+ for (const auto & element : elements_to_add) {
+ auto index = this->addElement(element);
+ handler.constitutive_law_index(element) = law_id;
+ handler.constitutive_law_local_numbering(element) = index;
+ }
+
+ this->resizeInternals();
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::removeElements(
+ const Array<Element> & elements_to_remove) {
+ AKANTU_DEBUG_IN();
+
+ auto el_begin = elements_to_remove.begin();
+ auto el_end = elements_to_remove.end();
+
+ if (elements_to_remove.empty()) {
+ return;
+ }
+
+ auto & mesh = handler.getMesh();
+
+ ElementTypeMapArray<Idx> constitutive_law_local_new_numbering(
+ "remove constitutive law filter elem", id);
+
+ constitutive_law_local_new_numbering.initialize(
+ mesh, _element_filter = &getElementFilter(),
+ _element_kind = _ek_not_defined, _with_nb_element = true);
+
+ ElementTypeMapArray<Idx> element_filter_tmp("element_filter_tmp", id);
+
+ element_filter_tmp.initialize(mesh, _element_filter = &getElementFilter(),
+ _element_kind = _ek_not_defined);
+
+ 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) {
+ constitutive_law_local_new_numbering(l_el) = Idx(-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);
+
+ constitutive_law_local_new_numbering(l_el) = new_id;
+ handler.constitutive_law_local_numbering(el) = new_id;
+
+ ++new_id;
+ ++element_id;
+ },
+ _element_filter = &getElementFilter(), _element_kind = _ek_not_defined);
+
+ for (auto ghost_type : ghost_types) {
+ for (const auto & type : getElementFilter().elementTypes(
+ _ghost_type = ghost_type, _element_kind = _ek_not_defined)) {
+ getElementFilter(type, ghost_type)
+ .copy(element_filter_tmp(type, ghost_type));
+ }
+ }
+
+ this->removeIntegrationPoints(constitutive_law_local_new_numbering);
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::onElementsAdded(
+ const Array<Element> & /*unused*/, const NewElementsEvent & /*unused*/) {
+ this->resizeInternals();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::onElementsRemoved(
+ const Array<Element> & element_list,
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & /*event*/) {
+
+ auto my_num = handler.getInternalIndexFromID(getID());
+
+ ElementTypeMapArray<Idx> constitutive_law_local_new_numbering(
+ "remove constitutive law 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 getElementFilter().exists(type, gt) or
+ getElementFilter(type, gt).empty()) {
+ continue;
+ }
+
+ auto & elem_filter = getElementFilter(type, gt);
+ auto & law_indexes = this->handler.constitutive_law_index(type, gt);
+ auto & law_loc_num =
+ this->handler.constitutive_law_local_numbering(type, gt);
+ auto nb_element = this->handler.getMesh().getNbElement(type, gt);
+
+ // all constitutive laws will resized to the same size...
+ law_indexes.resize(nb_element);
+ law_loc_num.resize(nb_element);
+
+ if (not constitutive_law_local_new_numbering.exists(type, gt)) {
+ constitutive_law_local_new_numbering.alloc(elem_filter.size(), 1, type,
+ gt);
+ }
+
+ auto & law_renumbering = constitutive_law_local_new_numbering(type, gt);
+ const auto & renumbering = new_numbering(type, gt);
+ Array<Idx> elem_filter_tmp;
+ Int ni = 0;
+ Element el{type, 0, gt};
+
+ for (auto && [i, el_id] : enumerate(elem_filter)) {
+ el.element = el_id;
+
+ if (std::find(el_begin, el_end, el) == el_end) {
+ auto new_el = renumbering(el_id);
+ AKANTU_DEBUG_ASSERT(new_el != -1,
+ "A not removed element as been badly renumbered");
+ elem_filter_tmp.push_back(new_el);
+ law_renumbering(i) = ni;
+ law_indexes(new_el) = my_num;
+ law_loc_num(new_el) = ni;
+ ++ni;
+ } else {
+ law_renumbering(i) = -1;
+ }
+ }
+
+ elem_filter.resize(elem_filter_tmp.size());
+ elem_filter.copy(elem_filter_tmp);
+ }
+ }
+
+ this->removeIntegrationPoints(constitutive_law_local_new_numbering);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+template <typename T>
+inline void ConstitutiveLaw<ConstitutiveLawsHandler_>::packInternalFieldHelper(
+ const InternalField<T> & data_to_pack, CommunicationBuffer & buffer,
+ const Array<Element> & elements) const {
+ DataAccessor::packElementalDataHelper<T>(data_to_pack, buffer, elements,
+ data_to_pack.getFEEngine());
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+template <typename T>
+inline void
+ConstitutiveLaw<ConstitutiveLawsHandler_>::unpackInternalFieldHelper(
+ InternalField<T> & data_to_unpack, CommunicationBuffer & buffer,
+ const Array<Element> & elements) {
+ DataAccessor::unpackElementalDataHelper<T>(data_to_unpack, buffer, elements,
+ data_to_unpack.getFEEngine());
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+inline Element ConstitutiveLaw<ConstitutiveLawsHandler_>::convertToLocalElement(
+ const Element & global_element) const {
+#ifndef AKANTU_NDEBUG
+ auto model_law_index = handler.getConstitutiveLawByElement()(global_element);
+ auto law_index = handler.getConstitutiveLawIndex(this->name);
+ AKANTU_DEBUG_ASSERT(model_law_index == law_index,
+ "Conversion of a global element in a local element for "
+ "the wrong constitutive law "
+ << this->name << std::endl);
+#endif
+ auto local_element = global_element;
+ local_element.element =
+ handler.getConstitutiveLawLocalNumbering()(global_element);
+
+ return local_element;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+inline Element
+ConstitutiveLaw<ConstitutiveLawsHandler_>::convertToGlobalElement(
+ const Element & local_element) const {
+ auto global_element = local_element;
+ global_element.element = this->getElementFilter()(local_element);
+ return global_element;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+inline Idx
+ConstitutiveLaw<ConstitutiveLawsHandler_>::addElement(const Element & element) {
+ auto & el_filter = this->getElementFilter(element.type, element.ghost_type);
+ el_filter.push_back(element.element);
+ return el_filter.size() - 1;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+inline const Parameter &
+ConstitutiveLaw<ConstitutiveLawsHandler_>::getParam(const ID & param) const {
+ try {
+ return get(param);
+ } catch (...) {
+ AKANTU_EXCEPTION("No parameter " << param << " in the constitutive law"
+ << getID());
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+template <typename T>
+inline void
+ConstitutiveLaw<ConstitutiveLawsHandler_>::setParam(const ID & param, T value) {
+ try {
+ set<T>(param, value);
+ } catch (...) {
+ AKANTU_EXCEPTION("No parameter " << param << " in the constitutive law "
+ << getID());
+ }
+ updateInternalParameters();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+template <typename T>
+inline ElementTypeMap<Int>
+ConstitutiveLaw<ConstitutiveLawsHandler_>::getInternalDataPerElem(
+ const ID & field_id, ElementKind element_kind) const {
+
+ if (not this->template isInternal<T>(field_id, element_kind)) {
+ AKANTU_EXCEPTION("Cannot find internal field "
+ << id << " in the constitutive law " << this->name);
+ }
+
+ const auto & internal_field = this->template getInternal<T>(field_id);
+ const FEEngine & fe_engine = internal_field.getFEEngine();
+ auto nb_data_per_quad = internal_field.getNbComponent();
+
+ ElementTypeMap<Int> res;
+ for (auto ghost_type : ghost_types) {
+ 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 <class ConstitutiveLawsHandler_>
+template <typename T>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::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 the constitutive law " << this->name);
+ }
+
+ const auto & internal_field = this->template getInternal<T>(field_id);
+
+ 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
+ auto nb_element_dst = mesh.getNbElement(type, ghost_type);
+ // number of element in the internal field
+ auto nb_element_src = filter.size();
+ // number of quadrature points per elem
+ auto nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
+ // number of data per quadrature point
+ auto nb_data_per_quad = internal_field.getNbComponent();
+
+ 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);
+ }
+
+ if (nb_element_src == 0) {
+ continue;
+ }
+
+ // number of data per element
+ auto nb_data = nb_quad_per_elem * nb_data_per_quad;
+
+ 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 && [element, src_value] :
+ zip(filter, make_view(src_vect, nb_data))) {
+ it_dst[element] = src_value;
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawsHandler_>
+template <typename T>
+void ConstitutiveLaw<ConstitutiveLawsHandler_>::inflateInternal(
+ const std::string & field_id, const ElementTypeMapArray<T> & field,
+ GhostType ghost_type, ElementKind element_kind) {
+ if (not this->template isInternal<T>(field_id, element_kind)) {
+ AKANTU_EXCEPTION("Cannot find internal field " << id << " in material "
+ << this->name);
+ }
+
+ auto & internal_field = this->template getInternal<T>(field_id);
+ const auto & fe_engine = internal_field.getFEEngine();
+
+ for (auto && type : field.elementTypes(_ghost_type = 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 && [el, dest] :
+ zip(filter, make_view(dest_array, nb_component, nb_quad_per_elem))) {
+ dest = src[el];
+ }
+ }
+}
+
+} // namespace akantu
+
+#endif // AKANTU_CONSTITUTIVE_LAW_TMPL_HH
diff --git a/src/model/common/constitutive_laws/constitutive_laws_handler.hh b/src/model/common/constitutive_laws/constitutive_laws_handler.hh
new file mode 100644
index 000000000..f5cbe1a4c
--- /dev/null
+++ b/src/model/common/constitutive_laws/constitutive_laws_handler.hh
@@ -0,0 +1,353 @@
+/**
+ * @file constitutive_laws_handler.hh
+ *
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation ven mar 26 2021
+ *
+ * @brief A handler for multiple consistutive laws
+ *
+ * @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 "constitutive_law.hh" // NOLINT(pp_including_mainfile_in_preamble)
+#include "constitutive_law_selector.hh"
+#include "mesh.hh"
+#include "mesh_events.hh"
+#include "non_local_manager_callback.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_CONSTITUTIVE_LAWS_HANDLER_HH
+#define AKANTU_CONSTITUTIVE_LAWS_HANDLER_HH
+
+namespace akantu {
+class NonLocalManager;
+class ModelOptions;
+} // namespace akantu
+
+/* -------------------------------------------------------------------------- */
+namespace akantu {
+
+template <class ConstitutiveLawType, class Model_>
+class ConstitutiveLawsHandler : public Model_,
+ public DataAccessor<Element>,
+ public DataAccessor<Idx>,
+ public NonLocalManagerCallback {
+ /* ------------------------------------------------------------------------ */
+ /* Constructors/Destructors */
+ /* ------------------------------------------------------------------------ */
+public:
+ ConstitutiveLawsHandler(Mesh & mesh, const ModelType & type,
+ Int spatial_dimension, const ID & parent_id)
+ : Model_(mesh, type, spatial_dimension, parent_id),
+ constitutive_law_index("constitutive_law index", parent_id),
+ constitutive_law_local_numbering("constitutive_law local numbering",
+ parent_id) {
+ constitutive_law_selector =
+ std::make_shared<DefaultConstitutiveLawSelector>(
+ constitutive_law_index);
+
+ constitutive_law_index.initialize(mesh, _element_kind = _ek_not_defined,
+ _default_value = -1,
+ _with_nb_element = true);
+
+ constitutive_law_local_numbering.initialize(
+ mesh, _element_kind = _ek_not_defined, _with_nb_element = true);
+
+ this->registerDataAccessor(*this);
+
+ if (this->mesh.isDistributed()) {
+ auto & synchronizer = this->mesh.getElementSynchronizer();
+ this->registerSynchronizer(synchronizer,
+ SynchronizationTag::_constitutive_law_id);
+ }
+ }
+
+ class NewConstitutiveLawElementsEvent : public NewElementsEvent {
+ public:
+ AKANTU_GET_MACRO_NOT_CONST(ConstitutiveLawList, constitutive_law,
+ Array<Idx> &);
+ AKANTU_GET_MACRO(ConstitutiveLawList, constitutive_law, const Array<Idx> &);
+
+ protected:
+ Array<Idx> constitutive_law;
+ };
+
+ /* ------------------------------------------------------------------------ */
+ /* ConstitutiveLaws */
+ /* ------------------------------------------------------------------------ */
+public:
+ /// initialize the constitutive laws
+ void initFullImpl(const ModelOptions & options) override {
+ Model_::initFullImpl(options);
+ if (not this->parser.getLastParsedFile().empty()) {
+ auto && [model_section, is_empty] = this->getParserSection();
+ this->instantiateConstitutiveLaws(is_empty ? this->parser
+ : model_section);
+ this->initConstitutiveLaws();
+ }
+ }
+
+ /// register an empty constitutive_law of a given type
+ auto & registerNewConstitutiveLaw(const ID & cl_name, const ID & cl_type,
+ const ID & opt_param);
+
+ /// reassigns constitutive_laws depending on the constitutive_law selector
+ virtual void reassignConstitutiveLaw();
+
+ template <class Func> void for_each_constitutive_law(Func && func) {
+ for (auto && constitutive_law : constitutive_laws) {
+ std::forward<Func>(func)(*constitutive_law);
+ }
+ }
+
+ template <class Func> void for_each_constitutive_law(Func && func) const {
+ for (auto && constitutive_law : constitutive_laws) {
+ std::forward<Func>(func)(*constitutive_law);
+ }
+ }
+
+protected:
+ /// register a constitutive_law in the dynamic database
+ auto & registerNewConstitutiveLaw(const ParserSection & cl_section);
+
+ /// Initialize the constitutive laws
+ virtual void initConstitutiveLaws();
+
+ /// read the constitutive_law files to instantiate all the constitutive_laws
+ void instantiateConstitutiveLaws(ParserSection & parser_section);
+
+ /// set the element_id_by_constitutive_law and add the elements to the good
+ /// constitutive_laws
+ virtual void assignConstitutiveLawToElements(
+ const ElementTypeMapArray<Idx> * filter = nullptr);
+
+protected:
+ void splitElementByConstitutiveLaw(
+ const Array<Element> & elements,
+ std::vector<Array<Element>> & elements_per_cl) const;
+
+ template <typename Operation>
+ void splitByConstitutiveLaw(const Array<Element> & elements,
+ Operation && op) const;
+
+ /* ------------------------------------------------------------------------ */
+ /* Dumpable interface (kept for convenience) and dumper relative functions */
+ /* ------------------------------------------------------------------------ */
+public:
+ //! decide wether a field is a constitutive_law internal or not
+ bool isInternal(const std::string & field_name, ElementKind element_kind);
+
+ //! give the amount of data per element
+ virtual ElementTypeMap<Int>
+ getInternalDataPerElem(const std::string & field_name, ElementKind kind);
+
+ //! flatten a given constitutive_law internal field
+ template <class T = Real>
+ ElementTypeMapArray<T> & flattenInternal(const std::string & field_name,
+ ElementKind kind,
+ GhostType ghost_type = _not_ghost);
+
+ //! flatten all the registered constitutive_law internals
+ void flattenAllRegisteredInternals(ElementKind kind);
+
+ template <class T>
+ void inflateInternal(const std::string & field_name,
+ const ElementTypeMapArray<T> & field,
+ GhostType ghost_type, ElementKind kind);
+
+ /* ------------------------------------------------------------------------ */
+ /* Accessors */
+ /* ------------------------------------------------------------------------ */
+public:
+ /// get an iterable on the constitutive_laws
+ inline decltype(auto) getConstitutiveLaws();
+
+ /// get an iterable on the constitutive_laws
+ inline decltype(auto) getConstitutiveLaws() const;
+
+ /// get a particular constitutive_law (by numerical constitutive_law index)
+ inline auto & getConstitutiveLaw(Idx cl_index);
+
+ /// get a particular constitutive_law (by numerical constitutive_law index)
+ inline const auto & getConstitutiveLaw(Idx cl_index) const;
+
+ /// get a particular constitutive_law (by constitutive_law name)
+ inline auto & getConstitutiveLaw(const std::string & name);
+
+ /// get a particular constitutive_law (by constitutive_law name)
+ inline const auto & getConstitutiveLaw(const std::string & name) const;
+
+ /// get a particular constitutive_law (by constitutive_law name)
+ inline auto & getConstitutiveLaw(const Element & element);
+
+ /// get a particular constitutive_law (by constitutive_law name)
+ inline const auto & getConstitutiveLaw(const Element & element) const;
+
+ /// get a particular constitutive_law id from is name
+ [[nodiscard]] inline Idx
+ getConstitutiveLawIndex(const std::string & name) const;
+
+ /// give the number of constitutive_laws
+ [[nodiscard]] inline Int getNbConstitutiveLaws() const {
+ return constitutive_laws.size();
+ }
+
+ /// give the constitutive_law internal index from its id
+ [[nodiscard]] Int getInternalIndexFromID(const ID & id) const;
+
+ /// get the type to use for the parser
+ [[nodiscard]] ParserType getConstitutiveLawParserType() const {
+ return this->parser_type;
+ }
+
+protected:
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(ConstitutiveLawByElement,
+ constitutive_law_index);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(ConstitutiveLawLocalNumbering,
+ constitutive_law_local_numbering);
+
+public:
+ AKANTU_GET_MACRO_AUTO(ConstitutiveLawByElement, constitutive_law_index);
+ AKANTU_GET_MACRO_AUTO(ConstitutiveLawLocalNumbering,
+ constitutive_law_local_numbering);
+
+ /// vectors containing local constitutive_law element index for each global
+ /// element index
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ConstitutiveLawByElement,
+ constitutive_law_index, Idx);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ConstitutiveLawLocalNumbering,
+ constitutive_law_local_numbering, Idx);
+
+ AKANTU_GET_MACRO_NOT_CONST(ConstitutiveLawSelector,
+ *constitutive_law_selector,
+ ConstitutiveLawSelector &);
+
+ /// Access the non_local_manager interface
+ AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, NonLocalManager &);
+
+ /// Tells if the constitutive laws are non local
+ auto isNonLocal() const { return static_cast<bool>(non_local_manager); }
+
+ void
+ setConstitutiveLawSelector(const std::shared_ptr<ConstitutiveLawSelector> &
+ constitutive_law_selector) {
+ this->constitutive_law_selector = constitutive_law_selector;
+ }
+
+ /* ------------------------------------------------------------------------ */
+ /* Data Accessor inherited members */
+ /* ------------------------------------------------------------------------ */
+public:
+ [[nodiscard]] 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;
+
+ /* ------------------------------------------------------------------------ */
+ [[nodiscard]] Int
+ getNbData(const Array<Idx> & /*dofs*/,
+ const SynchronizationTag & /*tag*/) const override {
+ return 0;
+ }
+
+ void packData(CommunicationBuffer & /*buffer*/, const Array<Idx> & /*dofs*/,
+ const SynchronizationTag & /*tag*/) const override {}
+
+ void unpackData(CommunicationBuffer & /*buffer*/, const Array<Idx> & /*dofs*/,
+ const SynchronizationTag & /*tag*/) override {}
+
+ /* ------------------------------------------------------------------------ */
+ /* Mesh Event Handler inherited members */
+ /* ------------------------------------------------------------------------ */
+protected:
+ void onElementsAdded(const Array<Element> & element_list,
+ const NewElementsEvent & event) override;
+ void onElementsRemoved(const Array<Element> & element_list,
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & event) override;
+
+ /* ------------------------------------------------------------------------ */
+ /* NonLocalManager inherited members */
+ /* ------------------------------------------------------------------------ */
+protected:
+ void initializeNonLocal() override;
+
+ void updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) 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 constitutive_laws
+ void updateNonLocalInternal(ElementTypeMapReal & internal_flat,
+ GhostType ghost_type, ElementKind kind) override;
+
+ /* ------------------------------------------------------------------------ */
+ /* Class Members */
+ /* ------------------------------------------------------------------------ */
+protected:
+ /// Type to use for the parser
+ ParserType parser_type{ParserType::_constitutive_law};
+
+private:
+ /// mapping between constitutive_law name and constitutive_law internal id
+ std::map<std::string, Idx> constitutive_laws_names_to_id;
+
+ /// Arrays containing the constitutive_law index for each element
+ ElementTypeMapArray<Idx> constitutive_law_index;
+
+ /// Arrays containing the position in the element filter of the
+ /// constitutive_law (constitutive_law's local numbering)
+ ElementTypeMapArray<Idx> constitutive_law_local_numbering;
+
+ /// list of used constitutive_laws
+ std::vector<std::unique_ptr<ConstitutiveLawType>> constitutive_laws;
+
+ /// class defining of to choose a constitutive_law
+ std::shared_ptr<ConstitutiveLawSelector> constitutive_law_selector;
+
+ using flatten_internal_map = std::map<std::pair<std::string, ElementKind>,
+ std::unique_ptr<ElementTypeMapBase>>;
+
+ /// map a registered internals to be flattened for dump purposes
+ flatten_internal_map registered_internals;
+
+ /// tells if the constitutive_law are instantiated
+ bool are_constitutive_laws_instantiated{false};
+
+ /// non local manager
+ std::unique_ptr<NonLocalManager> non_local_manager;
+
+ template <class ConstitutiveLawsHandler> friend class ConstitutiveLaw;
+};
+
+} // namespace akantu
+
+#include "constitutive_laws_handler_tmpl.hh"
+
+#endif /* AKANTU_CONSTITUTIVE_LAWS_HANDLER_HH */
diff --git a/src/model/common/constitutive_laws/constitutive_laws_handler_tmpl.hh b/src/model/common/constitutive_laws/constitutive_laws_handler_tmpl.hh
new file mode 100644
index 000000000..f570ebd69
--- /dev/null
+++ b/src/model/common/constitutive_laws/constitutive_laws_handler_tmpl.hh
@@ -0,0 +1,679 @@
+/**
+ * @file constitutive_laws_handler_tmpl.hh
+ *
+ * @author Nicolas Richart <nicolas.richart@epfl.ch>
+ * @author Mohit Pundir <mohit.pundir@epfl.ch>
+ *
+ * @date creation ven mar 26 2021
+ *
+ * @brief Implementation of the consistutive laws handler.
+ *
+ * @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 "constitutive_law_non_local_interface.hh"
+#include "constitutive_law_selector_tmpl.hh"
+#include "constitutive_laws_handler.hh"
+#include "non_local_manager.hh"
+#include "parsable.hh"
+#include "mesh_iterators.hh"
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_CONSTITUTIVE_LAWS_HANDLER_TMPL_HH
+#define AKANTU_CONSTITUTIVE_LAWS_HANDLER_TMPL_HH
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline decltype(auto)
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaws() {
+ return make_transform_adaptor(
+ constitutive_laws, [](auto && value) -> decltype(auto) {
+ return aka::as_type<ConstitutiveLawType>(*value);
+ });
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline decltype(auto)
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaws()
+ const {
+ return make_transform_adaptor(
+ constitutive_laws, [](auto && value) -> decltype(auto) {
+ return aka::as_type<ConstitutiveLawType>(*value);
+ });
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline Idx
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLawIndex(
+ const std::string & name) const {
+ auto it = constitutive_laws_names_to_id.find(name);
+ if (it == constitutive_laws_names_to_id.end()) {
+ AKANTU_SILENT_EXCEPTION(
+ "The model " << this->id << " has no constitutive_law named " << name);
+ }
+
+ return it->second;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline auto &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaw(
+ Idx cl_index) {
+ AKANTU_DEBUG_ASSERT(cl_index < Idx(constitutive_laws.size()),
+ "The model " << this->id
+ << " has no constitutive law number "
+ << cl_index);
+ return *(constitutive_laws.at(cl_index));
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline const auto &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaw(
+ Idx cl_index) const {
+ AKANTU_DEBUG_ASSERT(cl_index < Idx(constitutive_laws.size()),
+ "The model " << this->id
+ << " has no constitutive law number "
+ << cl_index);
+ return *(constitutive_laws.at(cl_index));
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline auto &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaw(
+ const std::string & name) {
+ auto it = constitutive_laws_names_to_id.find(name);
+ if (it == constitutive_laws_names_to_id.end()) {
+ AKANTU_SILENT_EXCEPTION(
+ "The model " << this->id << " has no constitutive_law named " << name);
+ }
+
+ return *(constitutive_laws[it->second]);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline const auto &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaw(
+ const std::string & name) const {
+ auto it = constitutive_laws_names_to_id.find(name);
+ if (it == constitutive_laws_names_to_id.end()) {
+ AKANTU_SILENT_EXCEPTION(
+ "The model " << this->id << " has no constitutive_law named " << name);
+ }
+ return *(constitutive_laws[it->second]);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline auto &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaw(
+ const Element & element) {
+ auto index = constitutive_law_index(element);
+ return *(constitutive_laws[index]);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+inline const auto &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getConstitutiveLaw(
+ const Element & element) const {
+ auto index = constitutive_law_index(element);
+ return *(constitutive_laws[index]);
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+#define AKA_FWD_CL(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+template <typename Operation>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ splitByConstitutiveLaw(const Array<Element> & elements,
+ Operation && op) const {
+ std::vector<Array<Element>> elements_per_cl(constitutive_laws.size());
+ this->splitElementByConstitutiveLaw(elements, elements_per_cl);
+
+ for (auto && cl : zip(constitutive_laws, elements_per_cl)) {
+ AKA_FWD_CL(op)(AKA_FWD_CL(*std::get<0>(cl)), AKA_FWD_CL(std::get<1>(cl)));
+ }
+}
+
+#undef AKA_FWD_CL
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+auto & ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ registerNewConstitutiveLaw(const ParserSection & section) {
+ std::string cl_name;
+ std::string cl_type = section.getName();
+ std::string opt_param = section.getOption();
+
+ try {
+ std::string tmp = section.getParameter("name");
+ cl_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 constitutive_law of type \'"
+ << cl_type
+ << "\' in the input file has been defined without a name!");
+ }
+
+ auto && cl = this->registerNewConstitutiveLaw(cl_name, cl_type, opt_param);
+
+ cl.parseSection(section);
+
+ return cl;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+auto & ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ registerNewConstitutiveLaw(const ID & cl_name, const ID & cl_type,
+ const ID & opt_param) {
+ AKANTU_DEBUG_ASSERT(constitutive_laws_names_to_id.find(cl_name) ==
+ constitutive_laws_names_to_id.end(),
+ "A constitutive_law with this name '"
+ << cl_name << "' has already been registered. "
+ << "Please use unique names for constitutive_laws");
+
+ UInt cl_count = constitutive_laws.size();
+ constitutive_laws_names_to_id[cl_name] = cl_count;
+
+ std::stringstream sstr_cl;
+ sstr_cl << this->id << ":" << cl_count << ":" << cl_type;
+ ID cl_id = sstr_cl.str();
+
+ auto constitutive_law = ConstitutiveLawType::getFactory().allocate(
+ cl_type, this->spatial_dimension, opt_param,
+ aka::as_type<typename ConstitutiveLawType::ConstitutiveLawsHandler>(
+ *this),
+ cl_id);
+
+ constitutive_laws.push_back(std::move(constitutive_law));
+
+ return aka::as_type<ConstitutiveLawType>(*(constitutive_laws.back()));
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ instantiateConstitutiveLaws(ParserSection & parser_section) {
+ auto model_constitutive_laws =
+ parser_section.getSubSections(this->parser_type);
+ for (const auto & section : model_constitutive_laws) {
+ this->registerNewConstitutiveLaw(section);
+ }
+
+#ifdef AKANTU_DAMAGE_NON_LOCAL
+ for (auto & constitutive_law : constitutive_laws) {
+ if (dynamic_cast<ConstitutiveLawNonLocalInterface *>(
+ constitutive_law.get()) == nullptr) {
+ continue;
+ }
+
+ this->non_local_manager = std::make_unique<NonLocalManager>(
+ *this, *this, this->id + ":non_local_manager");
+ break;
+ }
+#endif
+
+ if (constitutive_laws.empty()) {
+ AKANTU_DEBUG_WARNING(
+ "No constitutive_laws where instantiated for the model " << this->id);
+ }
+ are_constitutive_laws_instantiated = true;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ assignConstitutiveLawToElements(const ElementTypeMapArray<Idx> * filter) {
+
+ for_each_element(
+ this->mesh,
+ [&](auto && element) {
+ Idx cl_index = (*constitutive_law_selector)(element);
+ AKANTU_DEBUG_ASSERT(cl_index < Idx(constitutive_laws.size()),
+ "The constitutive_law selector returned an index "
+ "that does not exists");
+ constitutive_law_index(element) = cl_index;
+ },
+ _element_filter = filter, _ghost_type = _not_ghost);
+
+ if (non_local_manager) {
+ non_local_manager->synchronize(*this,
+ SynchronizationTag::_constitutive_law_id);
+ }
+
+ for_each_element(
+ this->mesh,
+ [&](auto && element) {
+ auto cl_index = constitutive_law_index(element);
+ auto index = constitutive_laws[cl_index]->addElement(element);
+ constitutive_law_local_numbering(element) = index;
+ },
+ _element_filter = filter, _ghost_type = _not_ghost);
+
+ // synchronize the element constitutive_law arrays
+ this->synchronize(SynchronizationTag::_constitutive_law_id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType,
+ Model_>::initConstitutiveLaws() {
+ AKANTU_DEBUG_ASSERT(not constitutive_laws.empty(),
+ "No constitutive_law to initialize !");
+
+ this->assignConstitutiveLawToElements();
+
+ for (auto & constitutive_law : constitutive_laws) {
+ /// init internals properties
+ constitutive_law->initConstitutiveLaw();
+ }
+
+ this->synchronize(SynchronizationTag::_clh_init_cl);
+
+ if (this->non_local_manager) {
+ this->non_local_manager->initialize();
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+Int ConstitutiveLawsHandler<
+ ConstitutiveLawType, Model_>::getInternalIndexFromID(const ID & id) const {
+ AKANTU_DEBUG_IN();
+
+ auto it = constitutive_laws.begin();
+ auto end = constitutive_laws.end();
+
+ for (; it != end; ++it) {
+ if ((*it)->getID() == id) {
+ AKANTU_DEBUG_OUT();
+ return (it - constitutive_laws.begin());
+ }
+ }
+
+ AKANTU_DEBUG_OUT();
+ return -1;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType,
+ Model_>::reassignConstitutiveLaw() {
+ AKANTU_DEBUG_IN();
+
+ std::vector<Array<Element>> element_to_add(constitutive_laws.size());
+ std::vector<Array<Element>> element_to_remove(constitutive_laws.size());
+
+ for_each_element(this->mesh, [&](auto && element) {
+ auto old_constitutive_law = constitutive_law_index(element);
+ auto new_constitutive_law = (*constitutive_law_selector)(element);
+ if (old_constitutive_law != new_constitutive_law) {
+ element_to_add[new_constitutive_law].push_back(element);
+ element_to_remove[old_constitutive_law].push_back(element);
+ }
+ });
+
+ for (auto && data : enumerate(constitutive_laws)) {
+ auto cl_index = std::get<0>(data);
+ auto & cl = *std::get<1>(data);
+
+ cl.removeElements(element_to_remove[cl_index]);
+ cl.addElements(element_to_add[cl_index]);
+ }
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ updateDataForNonLocalCriterion(ElementTypeMapReal & criterion) {
+ const ID field_name = criterion.getName();
+ for (auto & constitutive_law : constitutive_laws) {
+ if (not constitutive_law->template isInternal<Real>(field_name,
+ _ek_regular)) {
+ continue;
+ }
+
+ for (auto ghost_type : ghost_types) {
+ constitutive_law->flattenInternal(field_name, criterion, ghost_type,
+ _ek_regular);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType,
+ Model_>::initializeNonLocal() {
+ this->non_local_manager->synchronize(
+ *this, SynchronizationTag::_constitutive_law_id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ insertIntegrationPointsInNeighborhoods(GhostType ghost_type) {
+ for (auto & cl : constitutive_laws) {
+ ConstitutiveLawNonLocalInterface * cl_non_local;
+ if ((cl_non_local = dynamic_cast<ConstitutiveLawNonLocalInterface *>(
+ cl.get())) == nullptr) {
+ continue;
+ }
+
+ auto & fe_engine = cl->getFEEngine();
+
+ ElementTypeMapArray<Real> quadrature_points_coordinates(
+ "quadrature_points_coordinates_tmp_nl", this->id);
+ quadrature_points_coordinates.initialize(
+ fe_engine, _nb_component = this->spatial_dimension,
+ _ghost_type = ghost_type);
+
+ for (const auto & type : quadrature_points_coordinates.elementTypes(
+ this->spatial_dimension, ghost_type)) {
+ fe_engine.computeIntegrationPointsCoordinates(
+ quadrature_points_coordinates(type, ghost_type), type, ghost_type);
+ }
+
+ cl_non_local->initConstitutiveLawNonLocal();
+
+ cl_non_local->insertIntegrationPointsInNeighborhoods(
+ ghost_type, quadrature_points_coordinates);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::updateLocalInternal(
+ ElementTypeMapReal & internal_flat, GhostType ghost_type,
+ ElementKind kind) {
+ const ID field_name = internal_flat.getName();
+ for (auto & constitutive_law : constitutive_laws) {
+ if (constitutive_law->template isInternal<Real>(field_name, kind)) {
+ constitutive_law->flattenInternal(field_name, internal_flat, ghost_type,
+ kind);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ updateNonLocalInternal(ElementTypeMapReal & internal_flat,
+ GhostType ghost_type, ElementKind kind) {
+
+ const ID field_name = internal_flat.getName();
+
+ for (auto & mat : constitutive_laws) {
+ if (not aka::is_of_type<ConstitutiveLawNonLocalInterface>(*mat)) {
+ continue;
+ }
+
+ auto & mat_non_local =
+ dynamic_cast<ConstitutiveLawNonLocalInterface &>(*mat);
+ mat_non_local.updateNonLocalInternals(internal_flat, field_name, ghost_type,
+ kind);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ splitElementByConstitutiveLaw(
+ const Array<Element> & elements,
+ std::vector<Array<Element>> & elements_per_cl) const {
+ for (const auto & el : elements) {
+ Element cl_el = el;
+ cl_el.element = this->constitutive_law_local_numbering(el);
+ auto cl_id = this->constitutive_law_index(el);
+ elements_per_cl[cl_id].push_back(cl_el);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+Int ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getNbData(
+ const Array<Element> & elements, const SynchronizationTag & tag) const {
+ Int size{0};
+
+ if (tag == SynchronizationTag::_constitutive_law_id) {
+ size += Int(elements.size()) * sizeof(Idx);
+ }
+
+ if (tag != SynchronizationTag::_constitutive_law_id) {
+ splitByConstitutiveLaw(elements, [&](auto && cl, auto && elements) {
+ size += cl.getNbData(elements, tag);
+ });
+ }
+ return size;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::packData(
+ CommunicationBuffer & buffer, const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
+ if (tag == SynchronizationTag::_constitutive_law_id) {
+ DataAccessor<Element>::packElementalDataHelper(constitutive_law_index,
+ buffer, elements);
+ }
+
+ if (tag != SynchronizationTag::_constitutive_law_id) {
+ splitByConstitutiveLaw(elements, [&](auto && cl, auto && elements) {
+ cl.packData(buffer, elements, tag);
+ });
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::unpackData(
+ CommunicationBuffer & buffer, const Array<Element> & elements,
+ const SynchronizationTag & tag) {
+ if (tag == SynchronizationTag::_constitutive_law_id) {
+ for (auto && element : elements) {
+ Idx recv_cl_index{};
+ buffer >> recv_cl_index;
+ Idx & cl_index = constitutive_law_index(element);
+ if (cl_index != -1) {
+ continue;
+ }
+
+ // add ghosts element to the correct constitutive_law
+ cl_index = recv_cl_index;
+ auto index = constitutive_laws[cl_index]->addElement(element);
+ constitutive_law_local_numbering(element) = index;
+ }
+ }
+
+ if (tag != SynchronizationTag::_constitutive_law_id) {
+ splitByConstitutiveLaw(elements, [&](auto && cl, auto && elements) {
+ cl.unpackData(buffer, elements, tag);
+ });
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::onElementsAdded(
+ const Array<Element> & element_list, const NewElementsEvent & event) {
+ this->constitutive_law_index.initialize(
+ this->mesh, _element_kind = _ek_not_defined, _with_nb_element = true,
+ _default_value = -1);
+ this->constitutive_law_local_numbering.initialize(
+ this->mesh, _element_kind = _ek_not_defined, _with_nb_element = true,
+ _default_value = -1);
+
+ ElementTypeMapArray<Idx> filter("new_element_filter", this->id);
+
+ for (const auto & elem : element_list) {
+ if (this->mesh.getSpatialDimension(elem.type) != this->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->assignConstitutiveLawToElements(&filter);
+
+ for (auto & constitutive_law : constitutive_laws) {
+ constitutive_law->onElementsAdded(element_list, event);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::onElementsRemoved(
+ const Array<Element> & element_list,
+ const ElementTypeMapArray<Idx> & new_numbering,
+ const RemovedElementsEvent & event) {
+ for (auto & constitutive_law : constitutive_laws) {
+ constitutive_law->onElementsRemoved(element_list, new_numbering, event);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+bool ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::isInternal(
+ const std::string & field_name, ElementKind element_kind) {
+ /// check if at least one constitutive_law contains field_id as an internal
+ for (auto & constitutive_law : constitutive_laws) {
+ auto is_internal =
+ constitutive_law->template isInternal<Real>(field_name, element_kind);
+ if (is_internal) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+ElementTypeMap<Int>
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::getInternalDataPerElem(
+ const std::string & field_name, ElementKind element_kind) {
+
+ if (!(this->isInternal(field_name, element_kind))) {
+ AKANTU_EXCEPTION("unknown internal " << field_name);
+ }
+
+ for (auto & constitutive_law : constitutive_laws) {
+ if (constitutive_law->template isInternal<Real>(field_name, element_kind)) {
+ return constitutive_law->template getInternalDataPerElem<Real>(
+ field_name, element_kind);
+ }
+ }
+
+ return ElementTypeMap<Int>();
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+template <class T>
+ElementTypeMapArray<T> &
+ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::flattenInternal(
+ const std::string & field_name, ElementKind kind,
+ const GhostType ghost_type) {
+ auto key = std::make_pair(field_name, kind);
+
+ ElementTypeMapArray<T> * internal_flat;
+
+ auto it = this->registered_internals.find(key);
+ if (it == this->registered_internals.end()) {
+ auto internal =
+ std::make_unique<ElementTypeMapArray<T>>(field_name, this->id);
+
+ internal_flat = internal.get();
+ this->registered_internals[key] = std::move(internal);
+ } else {
+ internal_flat = aka::as_type<ElementTypeMapArray<T>>(it->second.get());
+ }
+
+ for (auto type :
+ this->mesh.elementTypes(this->spatial_dimension, ghost_type, kind)) {
+ if (internal_flat->exists(type, ghost_type)) {
+ auto & internal = (*internal_flat)(type, ghost_type);
+ internal.resize(0);
+ }
+ }
+
+ for_each_constitutive_law([&](auto && constitutive_law) {
+ if (constitutive_law.template isInternal<T>(field_name, kind)) {
+ constitutive_law.flattenInternal(field_name, *internal_flat, ghost_type,
+ kind);
+ }
+ });
+
+ return *internal_flat;
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::
+ flattenAllRegisteredInternals(ElementKind kind) {
+ for (auto & internal : this->registered_internals) {
+ auto && [_id, _kind] = internal.first;
+ if (kind == _kind) {
+ this->flattenInternal(_id, kind);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <class ConstitutiveLawType, class Model_>
+template <class T>
+void ConstitutiveLawsHandler<ConstitutiveLawType, Model_>::inflateInternal(
+ const std::string & field_name, const ElementTypeMapArray<T> & field,
+ GhostType ghost_type, ElementKind kind) {
+ for_each_constitutive_law([&](auto && constitutive_law) {
+ if (constitutive_law.template isInternal<T>(field_name, kind)) {
+ constitutive_law.inflateInternal(field_name, field, ghost_type, kind);
+ } else {
+ AKANTU_ERROR("A internal of name \'"
+ << field_name
+ << "\' has not been defined in the constitutive law");
+ }
+ });
+}
+
+} // namespace akantu
+
+#endif /* AKANTU_CONSTITUTIVE_LAWS_HANDLER_TMPL_HH */
diff --git a/src/model/solid_mechanics/materials/internal_field.hh b/src/model/common/constitutive_laws/internal_field.hh
similarity index 61%
rename from src/model/solid_mechanics/materials/internal_field.hh
rename to src/model/common/constitutive_laws/internal_field.hh
index a293beecb..cc9bf75ae 100644
--- a/src/model/solid_mechanics/materials/internal_field.hh
+++ b/src/model/common/constitutive_laws/internal_field.hh
@@ -1,238 +1,282 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
+#include <memory>
+/* -------------------------------------------------------------------------- */
#ifndef AKANTU_INTERNAL_FIELD_HH_
#define AKANTU_INTERNAL_FIELD_HH_
namespace akantu {
-
-class Material;
+class ConstitutiveLawInternalHandler;
class FEEngine;
+} // namespace akantu
+
+namespace akantu {
+
+class InternalFieldBase {
+public:
+ InternalFieldBase(const ID & id) : id_(id) {}
+
+ virtual ~InternalFieldBase() = default;
+
+ /* ------------------------------------------------------------------------ */
+ InternalFieldBase(const InternalFieldBase & /*other*/) = default;
+ InternalFieldBase(InternalFieldBase && /*other*/) = default;
+ InternalFieldBase & operator=(const InternalFieldBase & /*other*/) = default;
+ InternalFieldBase & operator=(InternalFieldBase && /*other*/) = default;
+ /* ------------------------------------------------------------------------ */
+
+ /// activate the history of this field
+ virtual void initializeHistory() = 0;
+
+ /// resize the arrays and set the new element to 0
+ virtual void resize() = 0;
+
+ /// save the current values in the history
+ virtual void saveCurrentValues() = 0;
+
+ /// restore the previous values from the history
+ virtual void restorePreviousValues() = 0;
+
+ /// remove the quadrature points corresponding to suppressed elements
+ virtual void
+ removeIntegrationPoints(const ElementTypeMapArray<Idx> & new_numbering) = 0;
+
+ [[nodiscard]] virtual bool hasHistory() const = 0;
+
+ [[nodiscard]] auto getRegisterID() const { return id_; }
+
+protected:
+ ID id_;
+};
/**
- * class for the internal fields of materials
+ * class for the internal fields of constitutive law
* to store values for each quadrature
*/
-template <class Material_, typename T>
-class InternalFieldTmpl : public ElementTypeMapArray<T> {
+template <typename T>
+class InternalField : public InternalFieldBase, public ElementTypeMapArray<T> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
-public:
- using Material = Material_;
-
- InternalFieldTmpl(const ID & id, Material & material);
- ~InternalFieldTmpl() override;
-
+protected:
+ InternalField(const ID & id,
+ ConstitutiveLawInternalHandler & constitutive_law);
/// This constructor is only here to let cohesive elements compile
- InternalFieldTmpl(const ID & id, Material & material, FEEngine & fem,
- const ElementTypeMapArray<Idx> & element_filter);
+ InternalField(const ID & id,
+ ConstitutiveLawInternalHandler & constitutive_law,
+ const ID & fem_id,
+ const ElementTypeMapArray<Idx> & element_filter);
/// More general constructor
- InternalFieldTmpl(const ID & id, Material & material, Int dim, FEEngine & fem,
- const ElementTypeMapArray<Idx> & element_filter);
+ InternalField(const ID & id,
+ ConstitutiveLawInternalHandler & constitutive_law, Int dim,
+ const ID & fem_id,
+ const ElementTypeMapArray<Idx> & element_filter);
- InternalFieldTmpl(const ID & id,
- const InternalFieldTmpl<Material, T> & other);
+ InternalField(const ID & id, const InternalField<T> & other);
- auto operator=(const InternalFieldTmpl &) -> InternalFieldTmpl = delete;
+ friend class ConstitutiveLawInternalHandler;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
-public:
- /// function to reset the FEEngine for the internal field
- virtual void setFEEngine(FEEngine & fe_engine);
+protected:
+ /// initialize the field to a given number of component
+ virtual void initialize(Int nb_component);
+public:
/// 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();
+ void initializeHistory() override;
/// resize the arrays and set the new element to 0
- virtual void resize();
+ void resize() override;
/// 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();
+ void saveCurrentValues() override;
/// restore the previous values from the history
- virtual void restorePreviousValues();
+ void restorePreviousValues() override;
/// remove the quadrature points corresponding to suppressed elements
- virtual void
- removeIntegrationPoints(const ElementTypeMapArray<Int> & new_numbering);
+ void removeIntegrationPoints(
+ const ElementTypeMapArray<Idx> & new_numbering) override;
/// print the content
void printself(std::ostream & stream, int /*indent*/ = 0) const override;
/// get the default value
inline operator T() const;
- virtual auto getFEEngine() -> FEEngine & { return *fem; }
+ virtual auto getFEEngine() -> FEEngine & { return fem; }
- virtual auto getFEEngine() const -> const FEEngine & { return *fem; }
+ [[nodiscard]] virtual auto getFEEngine() const -> const FEEngine & {
+ return fem;
+ }
protected:
/// initialize the arrays in the ElementTypeMapArray<T>
void internalInitialize(Int nb_component);
/// set the values for new internals
virtual void setArrayValues(T * begin, T * end);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
-public:
+protected:
/// 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);
+ auto elementTypesImpl(Int /*dim*/ = _all_dimensions,
+ GhostType ghost_type = _not_ghost,
+ ElementKind /*kind*/ = _ek_not_defined) const ->
+ typename ElementTypeMapArray<T>::ElementTypesIteratorHelper override {
+ return ElementTypeMapArray<T>::elementTypesImpl(
+ this->spatial_dimension, ghost_type, this->element_kind);
}
+public:
/// 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
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 auto operator()(ElementType type, GhostType ghost_type = _not_ghost)
- -> Array<T> & {
- return ElementTypeMapArray<T>::operator()(type, ghost_type);
- }
-
- virtual auto operator()(ElementType type,
- GhostType ghost_type = _not_ghost) const
- -> const Array<T> & {
- return ElementTypeMapArray<T>::operator()(type, ghost_type);
- }
-
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 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 auto previous() -> InternalFieldTmpl & {
+ virtual InternalField<T> & previous() {
AKANTU_DEBUG_ASSERT(previous_values != nullptr,
"The history of the internal "
<< this->getID() << " has not been activated");
return *(this->previous_values);
}
- virtual auto previous() const -> const InternalFieldTmpl & {
+ virtual const InternalField<T> & previous() const {
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
- auto hasHistory() const -> bool { return (previous_values != nullptr); }
+ [[nodiscard]] auto hasHistory() const -> bool override {
+ return (previous_values != nullptr);
+ }
/// get the kind treated by the internal
AKANTU_GET_MACRO_AUTO(ElementKind, element_kind);
/// return the number of components
AKANTU_GET_MACRO_AUTO(NbComponent, nb_component);
/// return the spatial dimension corresponding to the internal element type
/// loop filter
AKANTU_GET_MACRO_AUTO(SpatialDimension, spatial_dimension);
+ Int & getRelease(ElementType type, GhostType ghost_type) {
+ return releases(type, ghost_type);
+ }
+
+ Int getRelease(ElementType type, GhostType ghost_type) const {
+ return releases(type, ghost_type);
+ }
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
- /// the material for which this is an internal parameter
- Material & material;
+ /// the constitutive_law for which this is an internal parameter
+ ConstitutiveLawInternalHandler & constitutive_law;
/// the fem containing the mesh and the element informations
- FEEngine * fem{nullptr};
+ FEEngine & fem;
/// Element filter if needed
const ElementTypeMapArray<Int> & element_filter;
/// default value
T default_value{};
/// spatial dimension of the element to consider
Int spatial_dimension{0};
/// ElementKind of the element to consider
ElementKind element_kind{_ek_regular};
/// Number of component of the internal field
Int nb_component{0};
/// Is the field initialized
bool is_init{false};
/// previous values
- std::unique_ptr<InternalFieldTmpl<Material, T>> previous_values;
+ std::shared_ptr<InternalField<T>> previous_values;
+
+ ElementTypeMap<Int> releases;
};
/// standard output stream operator
-template <class Material, typename T>
-inline auto operator<<(std::ostream & stream, const InternalFieldTmpl<Material, T> & _this)
- -> std::ostream & {
+template <typename T>
+inline std::ostream & operator<<(std::ostream & stream,
+ const InternalField<T> & _this) {
_this.printself(stream);
return stream;
}
-template <typename T> using InternalField = InternalFieldTmpl<Material, T>;
+// 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/common/constitutive_laws/internal_field_tmpl.hh
similarity index 56%
rename from src/model/solid_mechanics/materials/internal_field_tmpl.hh
rename to src/model/common/constitutive_laws/internal_field_tmpl.hh
index da9f23555..f153354a6 100644
--- a/src/model/solid_mechanics/materials/internal_field_tmpl.hh
+++ b/src/model/common/constitutive_laws/internal_field_tmpl.hh
@@ -1,324 +1,306 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "constitutive_law.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 <typename T>
+InternalField<T>::InternalField(
+ const ID & id, ConstitutiveLawInternalHandler & constitutive_law, Int dim,
+ const ID & fem_id, const ElementTypeMapArray<Idx> & element_filter)
+ : InternalFieldBase(id), ElementTypeMapArray<T>(id,
+ constitutive_law.getID()),
+ constitutive_law(constitutive_law),
+ fem(constitutive_law.getFEEngine(fem_id)), element_filter(element_filter),
+ spatial_dimension(dim) {}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-InternalFieldTmpl<Material, T>::InternalFieldTmpl(
- const ID & id, Material & material, FEEngine & fem,
- const ElementTypeMapArray<Idx> & element_filter)
- : ElementTypeMapArray<T>(id, material.getID()), material(material),
- fem(&fem), element_filter(element_filter),
- spatial_dimension(material.getSpatialDimension()) {}
+template <typename T>
+InternalField<T>::InternalField(
+ const ID & id, ConstitutiveLawInternalHandler & constitutive_law)
+ : InternalField(id, constitutive_law,
+ constitutive_law.getSpatialDimension(), "",
+ constitutive_law.getElementFilter()) {}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-InternalFieldTmpl<Material, T>::InternalFieldTmpl(
- 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 <typename T>
+InternalField<T>::InternalField(
+ const ID & id, ConstitutiveLawInternalHandler & constitutive_law,
+ const ID & fem_id, const ElementTypeMapArray<Idx> & element_filter)
+ : InternalField(id, constitutive_law,
+ constitutive_law.getSpatialDimension(), fem_id,
+ element_filter) {}
/* -------------------------------------------------------------------------- */
-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),
+template <typename T>
+InternalField<T>::InternalField(const ID & id, const InternalField<T> & other)
+ : InternalFieldBase(id), ElementTypeMapArray<T>(
+ id, other.constitutive_law.getID()),
+ constitutive_law(other.constitutive_law), 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) {
+template <typename T>
+void InternalField<T>::setElementKind(ElementKind element_kind) {
this->element_kind = element_kind;
}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::initialize(UInt nb_component) {
+template <typename T> void InternalField<T>::initialize(Int 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 <typename T> void InternalField<T>::initializeHistory() {
+ if (not previous_values) {
+ previous_values = std::shared_ptr<InternalField<T>>(
+ new InternalField<T>("previous_" + this->getID(), *this));
}
}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::resize() {
- if (!this->is_init) {
+template <typename T> void InternalField<T>::resize() {
+ if (not 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);
+ ElementTypeMap<Int> old_sizes;
+ for (auto ghost_type : ghost_types) {
+ for (const auto & type : this->filterTypes(ghost_type)) {
+ if (this->exists(type, ghost_type)) {
+ old_sizes(type, ghost_type) = this->operator()(type, ghost_type).size();
} else {
- vect = &(this->alloc(nb_element * nb_quadrature_points, nb_component,
- type, ghost));
+ old_sizes(type, ghost_type) = 0;
}
+ }
+ }
+
+ ElementTypeMapArray<T>::initialize(
+ fem, _element_filter = &element_filter, _element_kind = element_kind,
+ _nb_component = nb_component, _with_nb_element = true,
+ _do_not_default = true);
+
+ for (auto ghost_type : ghost_types) {
+ for (const auto & type : this->elementTypes(ghost_type)) {
+ auto & vect = this->operator()(type, ghost_type);
+ auto old_size = old_sizes(type, ghost_type);
+ auto new_size = vect.size();
+ this->setArrayValues(vect.data() + old_size * vect.getNbComponent(),
+ vect.data() + new_size * vect.getNbComponent());
- this->setArrayValues(vect->data() + old_size * vect->getNbComponent(),
- vect->data() + new_size * vect->getNbComponent());
+ this->releases(type, ghost_type) += 1;
}
}
+
+ if (this->previous_values) {
+ this->previous_values->resize();
+ }
}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::setDefaultValue(const T & value) {
+template <typename T> void InternalField<T>::setDefaultValue(const T & value) {
this->default_value = value;
this->reset();
}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::reset() {
+template <typename T> void InternalField<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();
+ auto & vect = (*this)(type, ghost_type);
this->setArrayValues(vect.data(),
vect.data() + vect.size() * vect.getNbComponent());
+ this->releases(type, ghost_type) += 1;
}
}
}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::internalInitialize(Int nb_component) {
- if (!this->is_init) {
+template <typename T>
+void InternalField<T>::internalInitialize(Int nb_component) {
+ if (not this->is_init) {
this->nb_component = nb_component;
+ this->is_init = true;
+ } else {
+ resize();
+ return;
+ }
- for (auto ghost : ghost_types) {
- for (const auto & type : this->filterTypes(ghost)) {
- 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);
- }
- }
+ for (auto ghost_type : ghost_types) {
+ for (const auto & type : this->filterTypes(ghost_type)) {
+ this->releases(type, ghost_type) = -1;
}
-
- this->material.registerInternal(*this);
- this->is_init = true;
}
+
+ ElementTypeMapArray<T>::initialize(
+ fem, _element_filter = &element_filter, _element_kind = element_kind,
+ _nb_component = nb_component, _with_nb_element = true,
+ _do_not_default = 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) {
+template <typename T>
+void InternalField<T>::setArrayValues(T * begin, T * end) {
for (; begin < end; ++begin) {
*begin = this->default_value;
}
}
/* -------------------------------------------------------------------------- */
-template <class Material, typename T>
-void InternalFieldTmpl<Material, T>::saveCurrentValues() {
+template <typename T> void InternalField<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() {
+template <typename T> void InternalField<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(
+template <typename T>
+void InternalField<T>::removeIntegrationPoints(
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 auto & renumbering = new_numbering(type, ghost_type);
- auto nb_quad_per_elem = fem->getNbIntegrationPoints(type, ghost_type);
+ 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;
+ 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(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 {
+template <typename T>
+void InternalField<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;
+ stream << "\n";
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 {
+template <typename T> inline InternalField<T>::operator T() const {
return default_value;
}
} // namespace akantu
#endif /* AKANTU_INTERNAL_FIELD_TMPL_HH_ */
diff --git a/src/model/solid_mechanics/materials/random_internal_field.hh b/src/model/common/constitutive_laws/random_internal_field.hh
similarity index 83%
rename from src/model/solid_mechanics/materials/random_internal_field.hh
rename to src/model/common/constitutive_laws/random_internal_field.hh
index 02b4467c2..57fcdd784 100644
--- a/src/model/solid_mechanics/materials/random_internal_field.hh
+++ b/src/model/common/constitutive_laws/random_internal_field.hh
@@ -1,97 +1,102 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "internal_field.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_RANDOM_INTERNAL_FIELD_HH_
#define AKANTU_RANDOM_INTERNAL_FIELD_HH_
namespace akantu {
/**
* class for the internal fields of materials with a random
* distribution
*/
template <typename T, template <typename> class BaseField = InternalField,
template <typename> class Generator = RandomGenerator>
class RandomInternalField : public BaseField<T> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- using ParentMaterial = typename BaseField<T>::Material;
-
- RandomInternalField(const ID & id, ParentMaterial & material);
-
- ~RandomInternalField() override;
+ using BaseField<T>::BaseField;
+ friend class ConstitutiveLawInternalHandler;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
- RandomInternalField operator=(const RandomInternalField &) = delete;
-
public:
- AKANTU_GET_MACRO(RandomParameter, random_parameter,
- const RandomParameter<T> &);
+ std::shared_ptr<RandomInternalField> getPtr() {
+ return aka::as_type<RandomInternalField>(this->shared_from_this());
+ }
/// initialize the field to a given number of component
- void initialize(UInt nb_component) override;
+ void initialize(Int nb_component) override;
/// set the field to a given value
void setDefaultValue(const T & value) override;
/// set the specified random distribution to a given parameter
void setRandomDistribution(const RandomParameter<T> & param);
/// print the content
void printself(std::ostream & stream, int indent = 0) const override;
protected:
void setArrayValues(T * begin, T * end) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
inline operator Real() const;
+ AKANTU_GET_MACRO(RandomParameter, random_parameter,
+ const RandomParameter<T> &);
+
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// random parameter containing the distribution and base value
- RandomParameter<T> random_parameter;
+ RandomParameter<T> random_parameter{T()};
};
/// standard output stream operator
-template <typename T>
-inline std::ostream & operator<<(std::ostream & stream,
- const RandomInternalField<T> & _this) {
+template <typename T, template <typename> class BaseField = InternalField,
+ template <typename> class Generator = RandomGenerator>
+inline std::ostream &
+operator<<(std::ostream & stream,
+ const RandomInternalField<T, BaseField, Generator> & _this) {
_this.printself(stream);
return stream;
}
+template <typename T>
+using DefaultRandomInternalField =
+ RandomInternalField<T, InternalField, RandomGenerator>;
+
} // namespace akantu
#endif /* AKANTU_RANDOM_INTERNAL_FIELD_HH_ */
diff --git a/src/model/solid_mechanics/materials/random_internal_field_tmpl.hh b/src/model/common/constitutive_laws/random_internal_field_tmpl.hh
similarity index 85%
rename from src/model/solid_mechanics/materials/random_internal_field_tmpl.hh
rename to src/model/common/constitutive_laws/random_internal_field_tmpl.hh
index 5afe537ea..3630b6868 100644
--- a/src/model/solid_mechanics/materials/random_internal_field_tmpl.hh
+++ b/src/model/common/constitutive_laws/random_internal_field_tmpl.hh
@@ -1,115 +1,103 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "internal_field_tmpl.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_RANDOM_INTERNAL_FIELD_TMPL_HH_
#define AKANTU_RANDOM_INTERNAL_FIELD_TMPL_HH_
namespace akantu {
-/* -------------------------------------------------------------------------- */
-template <typename T, template <typename> class BaseField,
- template <typename> class Generator>
-RandomInternalField<T, BaseField, Generator>::RandomInternalField(
- const ID & id, ParentMaterial & material)
- : BaseField<T>(id, material), random_parameter(T()) {}
-
-/* -------------------------------------------------------------------------- */
-template <typename T, template <typename> class BaseField,
- template <typename> class Generator>
-RandomInternalField<T, BaseField, Generator>::~RandomInternalField() = default;
-
/* -------------------------------------------------------------------------- */
template <typename T, template <typename> class BaseField,
template <typename> class Generator>
void RandomInternalField<T, BaseField, Generator>::initialize(
- UInt nb_component) {
+ Int nb_component) {
this->internalInitialize(nb_component);
}
/* ------------------------------------------------------------------------ */
template <typename T, template <typename> class BaseField,
template <typename> class Generator>
void RandomInternalField<T, BaseField, Generator>::setDefaultValue(
const T & value) {
random_parameter.setBaseValue(value);
this->reset();
}
/* ------------------------------------------------------------------------ */
template <typename T, template <typename> class BaseField,
template <typename> class Generator>
void RandomInternalField<T, BaseField, Generator>::setRandomDistribution(
const RandomParameter<T> & param) {
random_parameter = param;
this->reset();
}
/* ------------------------------------------------------------------------ */
template <typename T, template <typename> class BaseField,
template <typename> class Generator>
void RandomInternalField<T, BaseField, Generator>::printself(
std::ostream & stream, int indent [[gnu::unused]]) const {
stream << "RandomInternalField [ ";
random_parameter.printself(stream);
stream << " ]";
#if !defined(AKANTU_NDEBUG)
if (AKANTU_DEBUG_TEST(dblDump)) {
stream << std::endl;
BaseField<T>::printself(stream, indent);
}
#endif
}
/* -------------------------------------------------------------------------- */
template <typename T, template <typename> class BaseField,
template <typename> class Generator>
void RandomInternalField<T, BaseField, Generator>::setArrayValues(T * begin,
T * end) {
random_parameter.template setValues<Generator>(begin, end);
}
/* -------------------------------------------------------------------------- */
template <typename T, template <typename> class BaseField,
template <typename> class Generator>
inline RandomInternalField<T, BaseField, Generator>::operator Real() const {
return random_parameter.getBaseValue();
}
/* -------------------------------------------------------------------------- */
template <>
inline void ParameterTyped<RandomInternalField<Real>>::setAuto(
const ParserParameter & in_param) {
Parameter::setAuto(in_param);
RandomParameter<Real> r = in_param;
param.setRandomDistribution(r);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_RANDOM_INTERNAL_FIELD_TMPL_HH_ */
diff --git a/src/model/common/dof_manager/dof_manager_default.cc b/src/model/common/dof_manager/dof_manager_default.cc
index ee108e124..361cc8c86 100644
--- a/src/model/common/dof_manager/dof_manager_default.cc
+++ b/src/model/common/dof_manager/dof_manager_default.cc
@@ -1,474 +1,472 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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<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 auto & equation_number = this->getLocalEquationsNumbers(dof_id);
auto nb_degree_of_freedoms = equation_number.size();
local_array.resize(nb_degree_of_freedoms / local_array.getNbComponent());
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 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<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();
const 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.data();
nb_elements = group_elements.size();
}
auto size_mat = nb_nodes_per_element * nb_degree_of_freedom_per_node;
Vector<Int> element_eq_nb(size_mat);
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.begin(), element_eq_nb.end(), element_eq_nb.begin(),
[&](auto & local) { return this->localToGlobalEquationNumber(local); });
if (ge_it != nullptr) {
++ge_it;
} else {
++cit;
}
for (Int i = 0; i < size_mat; ++i) {
auto c_irn = element_eq_nb(i);
if (c_irn < size) {
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<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_inline_impl.hh b/src/model/common/dof_manager/dof_manager_default_inline_impl.hh
index 6dda03a73..2092bebf4 100644
--- a/src/model/common/dof_manager/dof_manager_default_inline_impl.hh
+++ b/src/model/common/dof_manager/dof_manager_default_inline_impl.hh
@@ -1,30 +1,30 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_HH_
#define AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_HH_
namespace akantu {} // namespace akantu
-#endif /* __AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_HH_ */
+#endif /* AKANTU_DOF_MANAGER_DEFAULT_INLINE_IMPL_HH */
diff --git a/src/model/common/model_solver.cc b/src/model/common/model_solver.cc
index fc67c5f95..8d1b7258d 100644
--- a/src/model/common/model_solver.cc
+++ b/src/model/common/model_solver.cc
@@ -1,387 +1,381 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_solver.hh"
#include "dof_manager.hh"
#include "dof_manager_default.hh"
#include "mesh.hh"
#include "non_linear_solver.hh"
#include "time_step_solver.hh"
#if defined(AKANTU_USE_PETSC)
#include "dof_manager_petsc.hh"
#endif
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
template <typename T> static T getOptionToType(const std::string & opt_str) {
std::stringstream sstr(opt_str);
T opt;
sstr >> opt;
return opt;
}
/* -------------------------------------------------------------------------- */
ModelSolver::ModelSolver(Mesh & mesh, const ModelType & type, const ID & id)
- : Parsable(ParserType::_model, id), model_type(type), parent_id(id),
- mesh(mesh) {}
-
-/* -------------------------------------------------------------------------- */
-ModelSolver::~ModelSolver() = default;
+ : Parsable(ParserType::_model, id), model_type(type), id(id), mesh(mesh) {}
/* -------------------------------------------------------------------------- */
std::tuple<ParserSection, bool> ModelSolver::getParserSection() {
auto sub_sections = getStaticParser().getSubSections(ParserType::_model);
auto it = std::find_if(
sub_sections.begin(), sub_sections.end(), [&](auto && section) {
auto type = getOptionToType<ModelType>(section.getName());
// default id should be the model type if not defined
- std::string name = section.getParameter("name", this->parent_id);
- return type == model_type and name == this->parent_id;
+ std::string name = section.getParameter("name", this->id);
+ return type == model_type and name == this->id;
});
if (it == sub_sections.end()) {
return std::make_tuple(ParserSection(), true);
}
return std::make_tuple(*it, false);
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<DOFManager>
-ModelSolver::initDOFManager(std::shared_ptr<DOFManager> dof_manager) {
+ModelSolver::initDOFManager(const std::shared_ptr<DOFManager> & dof_manager) {
if (dof_manager) {
this->dof_manager = dof_manager;
this->setDOFManager(*this->dof_manager);
return this->dof_manager;
}
// default without external solver activated at compilation same as mumps that
// is the historical solver but with only the lumped solver
ID solver_type = "default";
#if defined(AKANTU_USE_MUMPS)
solver_type = "default";
#elif defined(AKANTU_USE_PETSC)
solver_type = "petsc";
#endif
- ParserSection section;
- bool is_empty;
- std::tie(section, is_empty) = this->getParserSection();
+ auto && [section, is_empty] = this->getParserSection();
if (not is_empty) {
solver_type = section.getOption(solver_type);
return this->initDOFManager(section, solver_type);
}
return this->initDOFManager(solver_type);
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<DOFManager>
ModelSolver::initDOFManager(const ID & solver_type) {
if (dof_manager) {
AKANTU_EXCEPTION("The DOF manager for this model is already initialized !");
}
try {
this->dof_manager = DOFManagerFactory::getInstance().allocate(
- solver_type, mesh, this->parent_id + ":dof_manager_" + solver_type);
+ solver_type, mesh, this->id + ":dof_manager_" + solver_type);
} catch (...) {
AKANTU_EXCEPTION(
"To use the solver "
<< solver_type
<< " you will have to code it. This is an unknown solver type.");
}
this->setDOFManager(*this->dof_manager);
return this->dof_manager;
}
/* -------------------------------------------------------------------------- */
std::shared_ptr<DOFManager>
ModelSolver::initDOFManager(const ParserSection & section,
const ID & solver_type) {
this->initDOFManager(solver_type);
auto sub_sections = section.getSubSections(ParserType::_time_step_solver);
// parsing the time step solvers
for (auto && section : sub_sections) {
ID type = section.getName();
ID solver_id = section.getParameter("name", type);
auto tss_type = getOptionToType<TimeStepSolverType>(type);
auto tss_options = this->getDefaultSolverOptions(tss_type);
auto sub_solvers_sect =
section.getSubSections(ParserType::_non_linear_solver);
auto nb_non_linear_solver_section =
section.getNbSubSections(ParserType::_non_linear_solver);
auto nls_type = tss_options.non_linear_solver_type;
if (nb_non_linear_solver_section == 1) {
auto && nls_section = *(sub_solvers_sect.first);
nls_type = getOptionToType<NonLinearSolverType>(nls_section.getName());
} else if (nb_non_linear_solver_section > 0) {
AKANTU_EXCEPTION("More than one non linear solver are provided for the "
"time step solver "
<< solver_id);
}
this->getNewSolver(solver_id, tss_type, nls_type);
if (nb_non_linear_solver_section == 1) {
const auto & nls_section = *(sub_solvers_sect.first);
this->dof_manager->getNonLinearSolver(solver_id).parseSection(
nls_section);
}
auto sub_integrator_sections =
section.getSubSections(ParserType::_integration_scheme);
for (auto && is_section : sub_integrator_sections) {
const auto & dof_type_str = is_section.getName();
ID dof_id;
try {
ID tmp = is_section.getParameter("name");
dof_id = tmp;
} catch (...) {
AKANTU_EXCEPTION("No degree of freedom name specified for the "
"integration scheme of type "
<< dof_type_str);
}
auto it_type = getOptionToType<IntegrationSchemeType>(dof_type_str);
IntegrationScheme::SolutionType s_type = is_section.getParameter(
"solution_type", tss_options.solution_type[dof_id]);
this->setIntegrationScheme(solver_id, dof_id, it_type, s_type);
}
for (auto & is_type : tss_options.integration_scheme_type) {
if (!this->hasIntegrationScheme(solver_id, is_type.first)) {
this->setIntegrationScheme(solver_id, is_type.first, is_type.second,
tss_options.solution_type[is_type.first]);
}
}
}
if (section.hasParameter("default_solver")) {
ID default_solver = section.getParameter("default_solver");
if (this->hasSolver(default_solver)) {
this->setDefaultSolver(default_solver);
} else {
AKANTU_EXCEPTION(
"The solver \""
<< default_solver
<< "\" was not created, it cannot be set as default solver");
}
}
return this->dof_manager;
}
/* -------------------------------------------------------------------------- */
TimeStepSolver & ModelSolver::getSolver(const ID & solver_id) {
ID tmp_solver_id = solver_id;
if (tmp_solver_id.empty()) {
tmp_solver_id = this->default_solver_id;
}
TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(tmp_solver_id);
return tss;
}
/* -------------------------------------------------------------------------- */
const TimeStepSolver & ModelSolver::getSolver(const ID & solver_id) const {
ID tmp_solver_id = solver_id;
if (solver_id.empty()) {
tmp_solver_id = this->default_solver_id;
}
const TimeStepSolver & tss =
this->dof_manager->getTimeStepSolver(tmp_solver_id);
return tss;
}
/* -------------------------------------------------------------------------- */
TimeStepSolver & ModelSolver::getTimeStepSolver(const ID & solver_id) {
return this->getSolver(solver_id);
}
/* -------------------------------------------------------------------------- */
const TimeStepSolver &
ModelSolver::getTimeStepSolver(const ID & solver_id) const {
return this->getSolver(solver_id);
}
/* -------------------------------------------------------------------------- */
NonLinearSolver & ModelSolver::getNonLinearSolver(const ID & solver_id) {
return this->getSolver(solver_id).getNonLinearSolver();
}
/* -------------------------------------------------------------------------- */
const NonLinearSolver &
ModelSolver::getNonLinearSolver(const ID & solver_id) const {
return this->getSolver(solver_id).getNonLinearSolver();
}
/* -------------------------------------------------------------------------- */
bool ModelSolver::hasSolver(const ID & solver_id) const {
ID tmp_solver_id = solver_id;
if (solver_id.empty()) {
tmp_solver_id = this->default_solver_id;
}
if (not this->dof_manager) {
AKANTU_EXCEPTION("No DOF manager was initialized");
}
return this->dof_manager->hasTimeStepSolver(tmp_solver_id);
}
/* -------------------------------------------------------------------------- */
void ModelSolver::setDefaultSolver(const ID & solver_id) {
AKANTU_DEBUG_ASSERT(
this->hasSolver(solver_id),
"Cannot set the default solver to a solver that does not exists");
this->default_solver_id = solver_id;
}
/* -------------------------------------------------------------------------- */
void ModelSolver::solveStep(SolverCallback & callback, const ID & solver_id) {
AKANTU_DEBUG_IN();
TimeStepSolver & tss = this->getSolver(solver_id);
// make one non linear solve
tss.solveStep(callback);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void ModelSolver::solveStep(const ID & solver_id) {
solveStep(*this, solver_id);
}
/* -------------------------------------------------------------------------- */
void ModelSolver::getNewSolver(const ID & solver_id,
TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type) {
if (this->default_solver_id.empty()) {
this->default_solver_id = solver_id;
}
if (non_linear_solver_type == NonLinearSolverType::_auto) {
switch (time_step_solver_type) {
case TimeStepSolverType::_dynamic:
case TimeStepSolverType::_static:
non_linear_solver_type = NonLinearSolverType::_newton_raphson;
break;
case TimeStepSolverType::_dynamic_lumped:
non_linear_solver_type = NonLinearSolverType::_lumped;
break;
case TimeStepSolverType::_not_defined:
AKANTU_EXCEPTION(time_step_solver_type
<< " is not a valid time step solver type");
break;
}
}
this->initSolver(time_step_solver_type, non_linear_solver_type);
NonLinearSolver & nls = this->dof_manager->getNewNonLinearSolver(
solver_id, non_linear_solver_type);
this->dof_manager->getNewTimeStepSolver(solver_id, time_step_solver_type, nls,
*this);
}
/* -------------------------------------------------------------------------- */
Real ModelSolver::getTimeStep(const ID & solver_id) const {
const TimeStepSolver & tss = this->getSolver(solver_id);
return tss.getTimeStep();
}
/* -------------------------------------------------------------------------- */
void ModelSolver::setTimeStep(Real time_step, const ID & solver_id) {
TimeStepSolver & tss = this->getSolver(solver_id);
return tss.setTimeStep(time_step);
}
/* -------------------------------------------------------------------------- */
void ModelSolver::setIntegrationScheme(
const ID & solver_id, const ID & dof_id,
const IntegrationSchemeType & integration_scheme_type,
IntegrationScheme::SolutionType solution_type) {
TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id);
tss.setIntegrationScheme(dof_id, integration_scheme_type, solution_type);
}
/* -------------------------------------------------------------------------- */
void ModelSolver::setIntegrationScheme(
const ID & solver_id, const ID & dof_id,
std::unique_ptr<IntegrationScheme> & integration_scheme,
IntegrationScheme::SolutionType solution_type) {
TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id);
tss.setIntegrationScheme(dof_id, integration_scheme, solution_type);
}
/* -------------------------------------------------------------------------- */
bool ModelSolver::hasDefaultSolver() const {
return (not this->default_solver_id.empty());
}
/* -------------------------------------------------------------------------- */
bool ModelSolver::hasIntegrationScheme(const ID & solver_id,
const ID & dof_id) const {
TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id);
return tss.hasIntegrationScheme(dof_id);
}
/* -------------------------------------------------------------------------- */
void ModelSolver::predictor() {}
/* -------------------------------------------------------------------------- */
void ModelSolver::corrector() {}
/* -------------------------------------------------------------------------- */
TimeStepSolverType ModelSolver::getDefaultSolverType() const {
return TimeStepSolverType::_dynamic_lumped;
}
/* -------------------------------------------------------------------------- */
ModelSolverOptions
ModelSolver::getDefaultSolverOptions(__attribute__((unused))
const TimeStepSolverType & type) const {
ModelSolverOptions options;
options.non_linear_solver_type = NonLinearSolverType::_auto;
return options;
}
} // namespace akantu
diff --git a/src/model/common/model_solver.hh b/src/model/common/model_solver.hh
index 017029772..c935f7cac 100644
--- a/src/model/common/model_solver.hh
+++ b/src/model/common/model_solver.hh
@@ -1,191 +1,188 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "integration_scheme.hh"
#include "parsable.hh"
#include "solver_callback.hh"
#include "synchronizer_registry.hh"
/* -------------------------------------------------------------------------- */
#include <set>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MODEL_SOLVER_HH_
#define AKANTU_MODEL_SOLVER_HH_
namespace akantu {
class Mesh;
class DOFManager;
class TimeStepSolver;
class NonLinearSolver;
struct ModelSolverOptions;
} // namespace akantu
namespace akantu {
class ModelSolver : public Parsable,
public SolverCallback,
public SynchronizerRegistry {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
ModelSolver(Mesh & mesh, const ModelType & type, const ID & id);
- ~ModelSolver() override;
-
/// initialize the dof manager based on solver type passed in the input file
std::shared_ptr<DOFManager>
- initDOFManager(std::shared_ptr<DOFManager> dof_manager = nullptr);
+ initDOFManager(const std::shared_ptr<DOFManager> & dof_manager = nullptr);
/// initialize the dof manager based on the used chosen solver type
std::shared_ptr<DOFManager> initDOFManager(const ID & solver_type);
protected:
/// initialize the dof manager based on the used chosen solver type
std::shared_ptr<DOFManager> initDOFManager(const ParserSection & section,
const ID & solver_type);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// Callback for the model to instantiate the matricees when needed
virtual void initSolver(TimeStepSolverType /*time_step_solver_type*/,
NonLinearSolverType /*non_linear_solver_type*/) {}
/// get the section in the input file (if it exsits) corresponding to this
/// model
std::tuple<ParserSection, bool> getParserSection();
/// solve a step using a given pre instantiated time step solver and
/// non linear solver
virtual void solveStep(const ID & solver_id = "");
/// 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
virtual void solveStep(SolverCallback & callback, const ID & solver_id = "");
/// Initialize a time solver that can be used afterwards with its id
void getNewSolver(
const ID & solver_id, TimeStepSolverType time_step_solver_type,
NonLinearSolverType non_linear_solver_type = NonLinearSolverType::_auto);
/// set an integration scheme for a given dof and a given solver
void
setIntegrationScheme(const ID & solver_id, const ID & dof_id,
const IntegrationSchemeType & integration_scheme_type,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined);
/// set an externally instantiated integration scheme
void
setIntegrationScheme(const ID & solver_id, const ID & dof_id,
std::unique_ptr<IntegrationScheme> & integration_scheme,
IntegrationScheme::SolutionType solution_type =
IntegrationScheme::_not_defined);
/* ------------------------------------------------------------------------ */
/* SolverCallback interface */
/* ------------------------------------------------------------------------ */
public:
/// Predictor interface for the callback
void predictor() override;
/// Corrector interface for the callback
void corrector() override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// Default time step solver to instantiate for this model
- virtual TimeStepSolverType getDefaultSolverType() const;
+ [[nodiscard]] virtual TimeStepSolverType getDefaultSolverType() const;
/// Default configurations for a given time step solver
- virtual ModelSolverOptions
+ [[nodiscard]] virtual ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const;
/// get access to the internal dof manager
DOFManager & getDOFManager() { return *this->dof_manager; }
/// get the time step of a given solver
- Real getTimeStep(const ID & solver_id = "") const;
+ [[nodiscard]] Real getTimeStep(const ID & solver_id = "") const;
/// set the time step of a given solver
virtual void setTimeStep(Real time_step, const ID & solver_id = "");
- /// set the parameter 'param' of the solver 'solver_id'
- // template <typename T>
- // void set(const ID & param, const T & value, const ID & solver_id = "");
-
- /// get the parameter 'param' of the solver 'solver_id'
- // const Parameter & get(const ID & param, const ID & solver_id = "") const;
-
/// answer to the question "does the solver exists ?"
- bool hasSolver(const ID & solver_id) const;
+ [[nodiscard]] bool hasSolver(const ID & solver_id) const;
/// changes the current default solver
void setDefaultSolver(const ID & solver_id);
/// is a default solver defined
- bool hasDefaultSolver() const;
+ [[nodiscard]] bool hasDefaultSolver() const;
/// is an integration scheme set for a given solver and a given dof
- bool hasIntegrationScheme(const ID & solver_id, const ID & dof_id) const;
+ [[nodiscard]] bool hasIntegrationScheme(const ID & solver_id,
+ const ID & dof_id) const;
- TimeStepSolver & getTimeStepSolver(const ID & solver_id = "");
- NonLinearSolver & getNonLinearSolver(const ID & solver_id = "");
+ [[nodiscard]] TimeStepSolver & getTimeStepSolver(const ID & solver_id = "");
+ [[nodiscard]] NonLinearSolver & getNonLinearSolver(const ID & solver_id = "");
- const TimeStepSolver & getTimeStepSolver(const ID & solver_id = "") const;
- const NonLinearSolver & getNonLinearSolver(const ID & solver_id = "") const;
+ [[nodiscard]] const TimeStepSolver &
+ getTimeStepSolver(const ID & solver_id = "") const;
+ [[nodiscard]] const NonLinearSolver &
+ getNonLinearSolver(const ID & solver_id = "") const;
+
+ /// get id of model
+ AKANTU_GET_MACRO(ID, id, const ID &)
private:
- TimeStepSolver & getSolver(const ID & solver_id);
- const TimeStepSolver & getSolver(const ID & solver_id) const;
+ [[nodiscard]] TimeStepSolver & getSolver(const ID & solver_id);
+ [[nodiscard]] const TimeStepSolver & getSolver(const ID & solver_id) const;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
ModelType model_type;
/// Underlying dof_manager (the brain...)
std::shared_ptr<DOFManager> dof_manager;
-private:
- ID parent_id;
+ ID id;
+private:
/// Underlying mesh
Mesh & mesh;
/// Default time step solver to use
ID default_solver_id;
};
struct ModelSolverOptions {
NonLinearSolverType non_linear_solver_type;
std::map<ID, IntegrationSchemeType> integration_scheme_type;
std::map<ID, IntegrationScheme::SolutionType> solution_type;
};
} // namespace akantu
#endif /* AKANTU_MODEL_SOLVER_HH_ */
diff --git a/src/model/common/non_linear_solver/non_linear_solver_default.hh b/src/model/common/non_linear_solver/non_linear_solver_default.hh
index 2a5252cb3..69d124634 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_default.hh
+++ b/src/model/common/non_linear_solver/non_linear_solver_default.hh
@@ -1,35 +1,32 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_NON_LINEAR_SOLVER_DEFAULT_HH_
#define AKANTU_NON_LINEAR_SOLVER_DEFAULT_HH_
-#if defined(AKANTU_USE_MUMPS)
#include "non_linear_solver_linear.hh"
-#include "non_linear_solver_newton_raphson.hh"
-#endif
-
#include "non_linear_solver_lumped.hh"
+#include "non_linear_solver_newton_raphson.hh"
#endif /* AKANTU_NON_LINEAR_SOLVER_DEFAULT_HH_ */
diff --git a/src/model/common/non_linear_solver/non_linear_solver_linear.cc b/src/model/common/non_linear_solver/non_linear_solver_linear.cc
index 11bed4800..e9b405822 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_linear.cc
+++ b/src/model/common/non_linear_solver/non_linear_solver_linear.cc
@@ -1,72 +1,83 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_linear.hh"
#include "dof_manager_default.hh"
#include "solver_callback.hh"
/* -------------------------------------------------------------------------- */
+#if !defined(AKANTU_USE_MUMPS) && !defined(AKANTU_USE_PETSC)
+#include "sparse_solver_eigen.hh"
+namespace akantu {
+using SparseSolverType = SparseSolverEigen;
+}
+#else
+#include "sparse_solver_mumps.hh"
+namespace akantu {
+using SparseSolverType = SparseSolverMumps;
+}
+#endif
+
namespace akantu {
/* -------------------------------------------------------------------------- */
NonLinearSolverLinear::NonLinearSolverLinear(
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(dof_manager, "J", id + ":sparse_solver") {
-
+ dof_manager(dof_manager), solver(std::make_unique<SparseSolverType>(
+ dof_manager, "J", id + ":sparse_solver")) {
this->supported_type.insert(NonLinearSolverType::_linear);
this->checkIfTypeIsSupported();
}
/* -------------------------------------------------------------------------- */
NonLinearSolverLinear::~NonLinearSolverLinear() = default;
-/* ------------------------------------------------------------------------ */
+/* -------------------------------------------------------------------------- */
void NonLinearSolverLinear::solve(SolverCallback & solver_callback) {
solver_callback.beforeSolveStep();
this->dof_manager.updateGlobalBlockedDofs();
solver_callback.predictor();
solver_callback.assembleMatrix("J");
// Residual computed after J to allow the model to use K to compute the
// residual
this->assembleResidual(solver_callback);
- this->solver.solve();
+ this->solver->solve();
solver_callback.corrector();
if (solver_callback.canSplitResidual()) {
solver_callback.assembleResidual("internal");
} else {
this->assembleResidual(solver_callback);
}
solver_callback.afterSolveStep(true);
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/non_linear_solver/non_linear_solver_linear.hh b/src/model/common/non_linear_solver/non_linear_solver_linear.hh
index 1d97b83ba..00b3a174c 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_linear.hh
+++ b/src/model/common/non_linear_solver/non_linear_solver_linear.hh
@@ -1,67 +1,67 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "sparse_solver_mumps.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LINEAR_SOLVER_LINEAR_HH_
#define AKANTU_NON_LINEAR_SOLVER_LINEAR_HH_
namespace akantu {
class DOFManagerDefault;
-}
+class SparseSolver;
+} // namespace akantu
namespace akantu {
class NonLinearSolverLinear : public NonLinearSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLinearSolverLinear(DOFManagerDefault & dof_manager,
const NonLinearSolverType & non_linear_solver_type,
const ID & id = "non_linear_solver_linear");
~NonLinearSolverLinear() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// Function that solve the non linear system described by the dof manager and
/// the solver callback functions
void solve(SolverCallback & solver_callback) override;
- AKANTU_GET_MACRO_NOT_CONST(Solver, solver, SparseSolverMumps &);
- AKANTU_GET_MACRO(Solver, solver, const SparseSolverMumps &);
+ AKANTU_GET_MACRO_NOT_CONST(Solver, *solver, SparseSolver &);
+ AKANTU_GET_MACRO(Solver, *solver, const SparseSolver &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
DOFManagerDefault & dof_manager;
/// Sparse solver used for the linear solves
- SparseSolverMumps solver;
+ std::unique_ptr<SparseSolver> solver;
};
} // namespace akantu
#endif /* AKANTU_NON_LINEAR_SOLVER_LINEAR_HH_ */
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 9d6ccfdbb..50f47821c 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,199 +1,211 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
+#if !defined(AKANTU_USE_MUMPS) && !defined(AKANTU_USE_PETSC)
+#include "sparse_solver_eigen.hh"
+namespace akantu {
+using SparseSolverType = SparseSolverEigen;
+}
+#else
+#include "sparse_solver_mumps.hh"
+namespace akantu {
+using SparseSolverType = SparseSolverMumps;
+}
+#endif
+
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(dof_manager), solver(std::make_unique<SparseSolverType>(
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);
+ << this->convergence_criteria_normalized);
+
} 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);
Int nb_degree_of_freedoms = array.size();
auto arr_it = array.begin();
auto bld_it = blocked_dofs.begin();
Real norm = 0.;
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_newton_raphson.hh b/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.hh
index 9bb3c174b..f3985493c 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.hh
+++ b/src/model/common/non_linear_solver/non_linear_solver_newton_raphson.hh
@@ -1,98 +1,98 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LINEAR_SOLVER_NEWTON_RAPHSON_HH_
#define AKANTU_NON_LINEAR_SOLVER_NEWTON_RAPHSON_HH_
namespace akantu {
class DOFManagerDefault;
-class SparseSolverMumps;
+class SparseSolver;
class SolverVector;
} // namespace akantu
namespace akantu {
class NonLinearSolverNewtonRaphson : public NonLinearSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
NonLinearSolverNewtonRaphson(
DOFManagerDefault & dof_manager,
const NonLinearSolverType & non_linear_solver_type,
const ID & id = "non_linear_solver_newton_raphson");
~NonLinearSolverNewtonRaphson() override;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// Function that solve the non linear system described by the dof manager and
/// the solver callback functions
void solve(SolverCallback & solver_callback) override;
- AKANTU_GET_MACRO_NOT_CONST(Solver, *solver, SparseSolverMumps &);
- AKANTU_GET_MACRO(Solver, *solver, const SparseSolverMumps &);
+ AKANTU_GET_MACRO_NOT_CONST(Solver, *solver, SparseSolver &);
+ AKANTU_GET_MACRO(Solver, *solver, const SparseSolver &);
protected:
/// test the convergence compare norm of array to convergence_criteria
bool testConvergence(const SolverVector & solver_vector);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
DOFManagerDefault & dof_manager;
/// Sparse solver used for the linear solves
- std::unique_ptr<SparseSolverMumps> solver;
+ std::unique_ptr<SparseSolver> solver;
/// Type of convergence criteria
SolveConvergenceCriteria convergence_criteria_type;
/// convergence threshold
Real convergence_criteria;
/// convergence threshold
Real convergence_criteria_normalized;
/// Max number of iterations
int max_iterations;
/// Number of iterations at last solve call
int n_iter{0};
/// Convergence error at last solve call
Real error{0.};
/// Did the last call to solve reached convergence
bool converged{false};
/// Force a re-computation of the jacobian matrix
bool force_linear_recompute{true};
};
} // namespace akantu
#endif /* AKANTU_NON_LINEAR_SOLVER_NEWTON_RAPHSON_HH_ */
diff --git a/src/model/common/non_local_toolbox/neighborhood_base.cc b/src/model/common/non_local_toolbox/neighborhood_base.cc
index bc5176d66..bf28f0622 100644
--- a/src/model/common/non_local_toolbox/neighborhood_base.cc
+++ b/src/model/common/non_local_toolbox/neighborhood_base.cc
@@ -1,279 +1,254 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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()) {
this->registerDataAccessor(*this);
}
-/* -------------------------------------------------------------------------- */
-NeighborhoodBase::~NeighborhoodBase() = default;
-
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::initNeighborhood() {
AKANTU_DEBUG_INFO("Creating the grid");
this->createGrid();
}
/* ------------------------------------------------------------------------- */
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.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]);
+ auto q1_coords = this->quad_coordinates.get(q1);
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]);
+ auto q2_coords = this->quad_coordinates.get(q2);
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));
+ pair_list[q2.ghost_type].emplace_back(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;
+ for (const auto & [q1, q2] : pair_list.at(ghost_type)) {
+ pout << q1 << " " << q2 << " \n";
}
}
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<Int>("tag_1", _segment_2);
auto & nodes = mesh_accessor.getNodes();
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;
-
+ for (auto && [q1, q2] : pair_list.at(ghost_type)) {
auto add_node = [&](auto && q) {
- std::tie(std::ignore, inserted) =
- quad_to_nodes.insert(std::make_pair(q, node));
+ auto && [it, 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]);
+ auto && coords = this->quad_coordinates.get(q);
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;
-
- Idx node1 = quad_to_nodes[q1];
- Idx node2 = quad_to_nodes[q2];
+ for (const auto & [q1, q2] : pair_list.at(ghost_type)) {
+ auto && node1 = quad_to_nodes[q1];
+ auto && node2 = quad_to_nodes[q2];
connectivity.push_back(Vector<Idx>{node1, node2});
tag.push_back(node1 + 1);
if (node1 != node2) {
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]);
+ auto && q1_coords = this->quad_coordinates.get(q1);
- pout << "#neighbors for quad " << q1.global_num << std::endl;
- pout << q1_coords << std::endl;
+ pout << "#neighbors for quad " << q1.global_num << "\n";
+ pout << q1_coords << "\n";
for (auto && ghost_type2 : ghost_types) {
- for (auto && pair : pair_list[ghost_type2]) {
- if (q1 == pair.first && pair.second != q1) {
+ for (auto && pair : pair_list.at(ghost_type2)) {
+ if (q1 == pair.first and 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;
+ auto && q2_coords = this->quad_coordinates.get(q2);
+ pout << q2_coords << "\n";
}
}
}
}
}
/* -------------------------------------------------------------------------- */
void NeighborhoodBase::onElementsRemoved(
const Array<Element> & element_list,
const ElementTypeMapArray<Idx> & new_numbering,
const RemovedElementsEvent & event) {
AKANTU_DEBUG_IN();
auto & fem = this->model.getFEEngine();
Int nb_quad = 0;
auto cleanPoint = [&](auto && q) {
if (new_numbering.exists(q.type, q.ghost_type)) {
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);
+ for (auto && [q1, q2] : this->pair_list.at(ghost_type)) {
+ if (q1.ghost_type == _ghost) {
+ cleanPoint(q1);
}
- if (pair.second.ghost_type == _ghost) {
- cleanPoint(pair.second);
+ if (q2.ghost_type == _ghost) {
+ cleanPoint(q2);
}
}
}
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 7ae6ffe8d..061c2fdfd 100644
--- a/src/model/common/non_local_toolbox/neighborhood_base.hh
+++ b/src/model/common/non_local_toolbox/neighborhood_base.hh
@@ -1,140 +1,134 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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 "grid_synchronizer.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 VectorProxy<const 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<Idx> & new_numbering,
const RemovedElementsEvent & event);
protected:
/// create the grid
void createGrid();
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
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];
- }
+ const PairList & getPairLists(GhostType type) { return pair_list[type]; }
/* ------------------------------------------------------------------------ */
/* 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;
+ std::map<GhostType, PairList> 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 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/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc
index 027e710df..d25e5b350 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,280 +1,280 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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");
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)) {
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)) {
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 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<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)) {
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 (Int e = 0; e < nb_element; ++e) {
q.element = e;
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);
+ this->asynchronousSynchronize(SynchronizationTag::_nh_criterion);
/// compare to not-ghost neighbors
checkNeighbors(_not_ghost);
/// finish the exchange
- this->model.waitEndSynchronize(SynchronizationTag::_nh_criterion);
+ this->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;
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<Int> & nb_ghost_protected) {
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;
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);
}
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) = -1;
}
}
/// renumber remaining ghosts
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_inline_impl.hh b/src/model/common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh
index d08bff653..84efca98d 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,71 +1,71 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NEIGHBORHOOD_MAX_CRITERION_INLINE_IMPL_HH_
#define AKANTU_NEIGHBORHOOD_MAX_CRITERION_INLINE_IMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline Int
NeighborhoodMaxCriterion::getNbDataForElements(const Array<Element> & elements,
SynchronizationTag tag) const {
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());
+ criterion, buffer, elements, 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());
+ criterion, buffer, elements, 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 e220906c9..acfa9b7e0 100644
--- a/src/model/common/non_local_toolbox/non_local_manager.cc
+++ b/src/model/common/non_local_toolbox/non_local_manager.cc
@@ -1,560 +1,545 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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);
/// 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*/) {
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
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
Int max_id_size = 0;
- Int current_size = 0;
- NeighborhoodMap::const_iterator it;
for (const auto & id : make_keys_adaptor(neighborhoods)) {
- current_size = id.size();
- if (current_size > max_id_size) {
- max_id_size = current_size;
- }
+ max_id_size = std::max(max_id_size, Int(id.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
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();
+ nb_neighborhoods_per_proc(prank) = Int(neighborhoods.size());
static_communicator.allGather(nb_neighborhoods_per_proc);
/// compute the total number of neighborhoods
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
Int starting_index =
std::accumulate(nb_neighborhoods_per_proc.begin(),
nb_neighborhoods_per_proc.begin() + prank, 0);
/// store the names of local neighborhoods in the buffer
for (auto && data : enumerate(make_keys_adaptor(neighborhoods))) {
Int c = 0;
- auto i = std::get<0>(data);
+ Idx i = Idx(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 (Int i = 0; i < nb_neighborhoods_global; ++i) {
std::stringstream neighborhood_id;
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);
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);
+ auto 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 & 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() {
+void NonLocalManager::computeAllNonLocalContribution() {
/// 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->callback->computeNonLocalContribution(_not_ghost);
++this->compute_stress_calls;
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::cleanupExtraGhostElements() {
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);
}
}
/* -------------------------------------------------------------------------- */
void NonLocalManager::onElementsRemoved(
const Array<Element> & element_list,
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(Int nb_component,
ElementTypeMapReal & element_map,
const FEEngine & fee,
const ElementKind el_kind) {
auto & mesh = this->model.getMesh();
for (auto gt : ghost_types) {
for (auto type : mesh.elementTypes(spatial_dimension, gt, el_kind)) {
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<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 auto & renumbering = new_numbering(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()
<< ") "
"!!");
+ auto it = make_view(vect, nb_component * nb_quad_per_elem).begin();
+ auto tmp_it = make_view(tmp, nb_component * nb_quad_per_elem).begin();
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));
+ tmp_it[new_i] = it[i];
++new_size;
}
}
tmp.resize(new_size * nb_quad_per_elem);
vect.copy(tmp);
}
}
}
}
/* -------------------------------------------------------------------------- */
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;
+ size += it->second->nb_component * Int(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());
+ it->second->local, buffer, elements, 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());
+ it->second->local, buffer, elements, 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 a99e9105e..065010de7 100644
--- a/src/model/common/non_local_toolbox/non_local_manager.hh
+++ b/src/model/common/non_local_toolbox/non_local_manager.hh
@@ -1,271 +1,271 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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();
+ virtual void computeAllNonLocalContribution();
/// 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);
/// resizing of element type maps
void resizeElementTypeMap(Int nb_component, ElementTypeMapReal & element_map,
const FEEngine & fee,
ElementKind el_kind = _ek_regular);
/// remove integration points from element type maps
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<Int> & nb_ghost_protected);
/* ------------------------------------------------------------------------ */
/* DataAccessor kind of interface */
/* ------------------------------------------------------------------------ */
public:
/// get Nb data for synchronization in parallel
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<Idx> & new_numbering,
const RemovedElementsEvent & event) override;
void onElementsAdded(const Array<Element> & element_list,
const NewElementsEvent & event) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
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);
}
inline const ElementTypeMapArray<Real> & getJacobians() { return *jacobians; }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// the 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, Int nb_component)
: local(variable_name, id), non_local(nl_variable_name, id),
nb_component(nb_component) {}
ElementTypeMapReal local;
ElementTypeMapReal non_local;
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
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
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 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_manager_callback.hh b/src/model/common/non_local_toolbox/non_local_manager_callback.hh
index d45a7ce55..bc04b5230 100644
--- a/src/model/common/non_local_toolbox/non_local_manager_callback.hh
+++ b/src/model/common/non_local_toolbox/non_local_manager_callback.hh
@@ -1,56 +1,75 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_NON_LOCAL_MANAGER_CALLBACK_HH_
#define AKANTU_NON_LOCAL_MANAGER_CALLBACK_HH_
namespace akantu {
class NonLocalManager;
} // namespace akantu
namespace akantu {
class NonLocalManagerCallback {
public:
+ NonLocalManagerCallback() = default;
+ NonLocalManagerCallback(const NonLocalManagerCallback &) = default;
+ NonLocalManagerCallback(NonLocalManagerCallback &&) = default;
+ NonLocalManagerCallback &
+ operator=(const NonLocalManagerCallback &) = default;
+ NonLocalManagerCallback & operator=(NonLocalManagerCallback &&) = default;
+
+ virtual ~NonLocalManagerCallback() = default;
+
virtual void initializeNonLocal() {}
/* ------------------------------------------------------------------------ */
- virtual void insertIntegrationPointsInNeighborhoods(GhostType ghost_type) = 0;
+ virtual void
+ insertIntegrationPointsInNeighborhoods(GhostType /*ghost_type*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
- virtual void computeNonLocalStresses(GhostType ghost_type) = 0;
+ virtual void computeNonLocalContribution(GhostType /*ghost_type*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
/// update the values of the non local internal
- virtual void updateLocalInternal(ElementTypeMapReal & internal_flat,
- GhostType ghost_type, ElementKind kind) = 0;
+ virtual void updateLocalInternal(ElementTypeMapReal & /*internal_flat*/,
+ GhostType /*ghost_type*/,
+ ElementKind /*kind*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
/// copy the results of the averaging in the materials
- virtual void updateNonLocalInternal(ElementTypeMapReal & internal_flat,
- GhostType ghost_type,
- ElementKind kind) = 0;
+ virtual void updateNonLocalInternal(ElementTypeMapReal & /*internal_flat*/,
+ GhostType /*ghost_type*/,
+ ElementKind /*kind*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
};
} // namespace akantu
#endif /* AKANTU_NON_LOCAL_MANAGER_CALLBACK_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 e058180bb..7fa2e019f 100644
--- a/src/model/common/non_local_toolbox/non_local_neighborhood.hh
+++ b/src/model/common/non_local_toolbox/non_local_neighborhood.hh
@@ -1,113 +1,113 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "parsable.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_
#define AKANTU_NON_LOCAL_NEIGHBORHOOD_HH_
namespace akantu {
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,
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 Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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_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;
+ std::map<GhostType, std::unique_ptr<Array<Real>>> pair_weight;
/// weight function
std::shared_ptr<WeightFunction> weight_function;
};
} // namespace akantu
#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 84edc2190..99fe1873f 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,109 +1,106 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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) {
this->registerParam("radius", neighborhood_radius, 100.,
_pat_parsable | _pat_readable, "Non local radius");
}
-/* -------------------------------------------------------------------------- */
-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 (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 9f9edde7d..178e0c29f 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,124 +1,123 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(){};
+ virtual void computeWeights() {}
// compute the non-local counter part for a given element type map
virtual void
weightedAverageOnNeighbours(const ElementTypeMapReal & to_accumulate,
ElementTypeMapReal & accumulated,
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 Int getNbData(const Array<Element> &,
- const SynchronizationTag &) const override {
+ [[nodiscard]] 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_tmpl.hh b/src/model/common/non_local_toolbox/non_local_neighborhood_tmpl.hh
index a45861613..21d5dfa5a 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,248 +1,246 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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());
+ auto && weight_vect = *pair_weight[ghost_type];
- for (auto & pair : pair_list[ghost_type]) {
- std::forward<decltype(func)>(func)(pair.first, pair.second, *weight_it);
- ++weight_it;
+ for (auto && [pair, weight] :
+ zip(pair_list[ghost_type],
+ make_view(weight_vect, weight_vect.getNbComponent()))) {
+ auto && [q1, q2] = pair;
+ std::forward<decltype(func)>(func)(q1, q2, weight);
}
}
/* -------------------------------------------------------------------------- */
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());
+ auto && weight_vect = *pair_weight.at(ghost_type);
- for (auto & pair : pair_list[ghost_type]) {
- std::forward<decltype(func)>(func)(pair.first, pair.second, *weight_it);
- ++weight_it;
+ for (auto && [pair, weight] :
+ zip(pair_list.at(ghost_type),
+ make_view(weight_vect, weight_vect.getNbComponent()))) {
+ auto && [q1, q2] = pair;
+ std::forward<decltype(func)>(func)(q1, q2, weight);
}
}
/* -------------------------------------------------------------------------- */
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);
+ for (auto ghost_type : ghost_types) {
+ if (pair_weight.find(ghost_type) == pair_weight.end()) {
+ pair_weight[ghost_type] = std::make_unique<Array<Real>>(0, 2);
+ pair_list[ghost_type].resize(0);
+ }
+ }
+
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);
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 (not pair_weight[ghost_type]) {
pair_weight[ghost_type] =
std::make_unique<Array<Real>>(0, nb_weights_per_pair);
}
auto && pair_lists = pair_list[ghost_type];
auto && pair_weights = *pair_weight[ghost_type];
pair_weights.resize(pair_lists.size());
pair_weights.zero();
+ auto && jacobians = this->non_local_manager.getJacobians();
/// loop over all pairs in the current pair list array and their
/// corresponding weights
// Compute the weights
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 && 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);
+ const auto & q2_wJ = jacobians(q2);
/// compute distance between the two quadrature points
auto r = q1_coord.distance(q2_coord);
/// compute the weight for averaging on q1 based on the distance
weight(0) = q2_wJ * (*this->weight_function)(r, q1, q2);
quad_volumes_1 += weight(0);
- if (q2.ghost_type != _ghost && q1.global_num != q2.global_num) {
- const auto & q1_wJ = this->non_local_manager.getJacobians()(q1);
+ if (q2.ghost_type != _ghost and q1.global_num != q2.global_num) {
+ const auto & q1_wJ = jacobians(q1);
auto && quad_volumes_2 = quadrature_points_volumes(q2);
/// compute the weight for averaging on q2
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);
-
- auto q1_volume = quad_volumes_1(q1.global_num);
- auto ghost_type2 = q2.ghost_type;
- weight(0) *= 1. / q1_volume;
- if (ghost_type2 != _ghost) {
- auto q2_volume = quad_volumes_2(q2.global_num);
- weight(1) *= 1. / q2_volume;
- }
- });
+ foreach_weight(ghost_type,
+ [&](const auto & q1, const auto & q2, auto & weight) {
+ auto q1_volume = quadrature_points_volumes(q1);
+ auto ghost_type2 = q2.ghost_type;
+ weight(0) *= 1. / q1_volume;
+ if (ghost_type2 != _ghost) {
+ auto q2_volume = quadrature_points_volumes(q2);
+ 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();
auto prank = comm.whoAmI();
sstr << filename << "." << prank;
pout.open(sstr.str().c_str());
for (auto ghost_type : ghost_types) {
- AKANTU_DEBUG_ASSERT((pair_weight[ghost_type]),
+ AKANTU_DEBUG_ASSERT((pair_weight.at(ghost_type)),
"the weights have not been computed yet");
- auto & weights = *(pair_weight[ghost_type]);
- auto weights_it = weights.begin(2);
- for (Int i = 0; i < weights.size(); ++i, ++weights_it) {
- pout << "w1: " << (*weights_it)(0) << " w2: " << (*weights_it)(1)
- << std::endl;
+ const auto & weights = *pair_weight.at(ghost_type);
+ for (auto && weight : make_view(weights, 2)) {
+ pout << "w1: " << weight(0) << " w2: " << weight(1) << "\n";
}
}
}
/* -------------------------------------------------------------------------- */
template <class WeightFunction>
void NonLocalNeighborhood<WeightFunction>::weightedAverageOnNeighbours(
const ElementTypeMapReal & to_accumulate, ElementTypeMapReal & accumulated,
- Int 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,
+ [ghost_type2, &to_accumulate,
&accumulated](const auto & q1, const auto & q2, auto & weight) {
- 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];
+ auto && to_acc_2 = to_accumulate.get(q2);
+ auto && acc_1 = accumulated.get(q1);
acc_1 += weight(0) * to_acc_2;
if (ghost_type2 != _ghost) {
+ auto && to_acc_1 = to_accumulate.get(q1);
+ auto && acc_2 = accumulated.get(q2);
+
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() &&
+ if (this->weight_function->getUpdateRate() and
(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/solver_callback.cc b/src/model/common/solver_callback.cc
index c5865d647..2d13cf34e 100644
--- a/src/model/common/solver_callback.cc
+++ b/src/model/common/solver_callback.cc
@@ -1,44 +1,38 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_callback.hh"
#include "dof_manager.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
SolverCallback::SolverCallback(DOFManager & dof_manager)
: sc_dof_manager(&dof_manager) {}
-/* -------------------------------------------------------------------------- */
-SolverCallback::SolverCallback() = default;
-
-/* -------------------------------------------------------------------------- */
-SolverCallback::~SolverCallback() = default;
-
/* -------------------------------------------------------------------------- */
void SolverCallback::setDOFManager(DOFManager & dof_manager) {
this->sc_dof_manager = &dof_manager;
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/common/solver_callback.hh b/src/model/common/solver_callback.hh
index 426c6ea2d..d52320ac7 100644
--- a/src/model/common/solver_callback.hh
+++ b/src/model/common/solver_callback.hh
@@ -1,157 +1,169 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_SOLVER_CALLBACK_HH_
#define AKANTU_SOLVER_CALLBACK_HH_
namespace akantu {
class DOFManager;
}
namespace akantu {
class SolverCallback {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
explicit SolverCallback(DOFManager & dof_manager);
- explicit SolverCallback();
+ explicit SolverCallback() = default;
/* ------------------------------------------------------------------------ */
- virtual ~SolverCallback();
+ SolverCallback(const SolverCallback & other) = default;
+ SolverCallback(SolverCallback && other) = default;
+ SolverCallback & operator=(const SolverCallback & other) = default;
+ SolverCallback & operator=(SolverCallback && other) = default;
+ /* ------------------------------------------------------------------------ */
+ virtual ~SolverCallback() = default;
protected:
void setDOFManager(DOFManager & dof_manager);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// get the type of matrix needed
- virtual MatrixType getMatrixType(const ID &) const = 0;
+ [[nodiscard]] virtual MatrixType
+ getMatrixType(const ID & /*matrix_id*/) const {
+ return _mt_not_defined;
+ }
/// callback to assemble a Matrix
- virtual void assembleMatrix(const ID &) = 0;
+ virtual void assembleMatrix(const ID & /*matrix_id*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
/// callback to assemble a lumped Matrix
- virtual void assembleLumpedMatrix(const ID &) = 0;
+ virtual void assembleLumpedMatrix(const ID & /*matrix_id*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
/// callback to assemble the residual (rhs)
- virtual void assembleResidual() = 0;
+ virtual void assembleResidual() { AKANTU_TO_IMPLEMENT(); }
/// callback to assemble the rhs parts, (e.g. internal_forces +
/// external_forces)
virtual void assembleResidual(const ID & /*residual_part*/) {}
/* ------------------------------------------------------------------------ */
/* Dynamic simulations part */
/* ------------------------------------------------------------------------ */
/// callback for the predictor (in case of dynamic simulation)
virtual void predictor() {}
/// callback for the corrector (in case of dynamic simulation)
virtual void corrector() {}
/// tells if the residual can be computed in separated parts
- virtual bool canSplitResidual() const { return false; }
+ [[nodiscard]] virtual bool canSplitResidual() const { return false; }
/* ------------------------------------------------------------------------ */
/* management callbacks */
/* ------------------------------------------------------------------------ */
virtual void beforeSolveStep() {}
virtual void afterSolveStep(bool /*converged*/ = true) {}
- DOFManager & getSCDOFManager() { return *sc_dof_manager; }
+ [[nodiscard]] DOFManager & getSCDOFManager() { return *sc_dof_manager; }
protected:
/// DOFManager prefixed to avoid collision in multiple inheritance cases
DOFManager * sc_dof_manager{nullptr};
};
namespace debug {
class SolverCallbackResidualPartUnknown : public Exception {
public:
SolverCallbackResidualPartUnknown(const ID & residual_part)
: Exception(residual_part + " is not known here.") {}
};
} // namespace debug
/* -------------------------------------------------------------------------- */
class InterceptSolverCallback : public SolverCallback {
public:
InterceptSolverCallback(SolverCallback & solver_callback)
: solver_callback(solver_callback) {}
/// get the type of matrix needed
- MatrixType getMatrixType(const ID & matrix_id) const override {
+ [[nodiscard]] MatrixType getMatrixType(const ID & matrix_id) const override {
return solver_callback.getMatrixType(matrix_id);
}
/// callback to assemble a Matrix
void assembleMatrix(const ID & matrix_id) override {
solver_callback.assembleMatrix(matrix_id);
}
/// callback to assemble a lumped Matrix
void assembleLumpedMatrix(const ID & matrix_id) override {
solver_callback.assembleLumpedMatrix(matrix_id);
}
/// callback to assemble the residual (rhs)
void assembleResidual() override { solver_callback.assembleResidual(); }
/// callback to assemble the rhs parts, (e.g. internal_forces +
/// external_forces)
void assembleResidual(const ID & residual_part) override {
solver_callback.assembleResidual(residual_part);
}
/* ------------------------------------------------------------------------ */
/* Dynamic simulations part */
/* ------------------------------------------------------------------------ */
/// callback for the predictor (in case of dynamic simulation)
void predictor() override { solver_callback.predictor(); }
/// callback for the corrector (in case of dynamic simulation)
void corrector() override { solver_callback.corrector(); }
/// tells if the residual can be computed in separated parts
- bool canSplitResidual() const override {
+ [[nodiscard]] bool canSplitResidual() const override {
return solver_callback.canSplitResidual();
}
/* ------------------------------------------------------------------------ */
/* management callbacks */
/* ------------------------------------------------------------------------ */
void beforeSolveStep() override { solver_callback.beforeSolveStep(); }
void afterSolveStep(bool converged = true) override {
solver_callback.afterSolveStep(converged);
}
protected:
SolverCallback & solver_callback;
};
} // namespace akantu
#endif /* AKANTU_SOLVER_CALLBACK_HH_ */
diff --git a/src/model/contact_mechanics/contact_detector.hh b/src/model/contact_mechanics/contact_detector.hh
index f6ae6f27e..68bf57899 100644
--- a/src/model/contact_mechanics/contact_detector.hh
+++ b/src/model/contact_mechanics/contact_detector.hh
@@ -1,221 +1,221 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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
std::pair<BBox, std::unique_ptr<SpatialGrid<Idx>>> globalSearch() const;
/// performs local search to find closet master node to a slave node
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
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,
Eigen::MatrixBase<Derived> & coords) const;
/// computes the optimal cell size for grid
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<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<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<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,
Eigen::MatrixBase<Derived> & normal) const;
/// extracts vectors which forms the plane of element
template <class Derived>
inline void vectorsAlongElement(const Element & el,
Eigen::MatrixBase<Derived> & vectors) const;
/// computes the gap between slave and its projection on master
/// surface
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
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
Int max_iterations;
/// tolerance for extending a master elements on all sides
Real extension_tolerance;
/// Mesh
Mesh & mesh;
/// dimension of the model
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<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"
+#include "contact_detector_inline_impl.hh"
-#endif /* __AKANTU_CONTACT_DETECTOR_HH__ */
+#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.hh
similarity index 98%
rename from src/model/contact_mechanics/contact_detector_inline_impl.cc
rename to src/model/contact_mechanics/contact_detector_inline_impl.hh
index e41bc9dd2..556fb23ee 100644
--- a/src/model/contact_mechanics/contact_detector_inline_impl.cc
+++ b/src/model/contact_mechanics/contact_detector_inline_impl.hh
@@ -1,289 +1,291 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
/* -------------------------------------------------------------------------- */
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);
});
}
/* -------------------------------------------------------------------------- */
template <class Derived>
inline void ContactDetector::coordinatesOfElement(
const Element & el, Eigen::MatrixBase<Derived> & coords) const {
coords = mesh.extractNodalValuesFromElement(positions, el);
}
/* -------------------------------------------------------------------------- */
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<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<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);
Vector<Real> lower_bound = bbox.getLowerBounds().array() - max_bb;
Vector<Real> upper_bound = bbox.getUpperBounds().array() + 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) {
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<Idx>
ContactDetector::constructConnectivity(Idx & slave,
const Element & master) const {
auto && master_conn = this->mesh.getConnectivity(master);
Vector<Idx> elem_conn(master_conn.size() + 1);
elem_conn[0] = slave;
elem_conn.block(1, 0, master_conn.size(), 1) = master_conn;
return elem_conn;
}
/* -------------------------------------------------------------------------- */
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: {
normal = Math::normal(vectors);
break;
}
case 3: {
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 = 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]);
}
auto projection = (outside - inside).dot(normal);
if (projection < 0) {
normal *= -1.0;
}
}
/* -------------------------------------------------------------------------- */
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) = coords(i + 1) - coords(0);
}
}
/* -------------------------------------------------------------------------- */
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);
}
}
}
/* -------------------------------------------------------------------------- */
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
auto it = std::find_if(
contact_pairs.begin(), contact_pairs.end(),
[slave_node](auto && pair) { return pair.first == slave_node; });
master_node = it->second;
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 : filter_if(slave_elements, [](auto && element) {
- return element.kind() == _ek_regular;
- })) {
+ auto predicate = [](auto && element) {
+ return element.kind() == _ek_regular;
+ };
+
+ for (auto && element : filter_if(slave_elements, predicate)) {
auto && connectivity = this->mesh.getConnectivity(element);
auto coords = mesh.extractNodalValuesFromElement(positions, element);
// finding the normal at slave node by averaging of normals
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 ce8bac30f..afcbf5819 100644
--- a/src/model/contact_mechanics/contact_element.hh
+++ b/src/model/contact_mechanics/contact_element.hh
@@ -1,76 +1,76 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#ifndef AKANTU_CONTACT_ELEMENT_HH_
+#define AKANTU_CONTACT_ELEMENT_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
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__ */
+#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 a2f2d0616..e260c6693 100644
--- a/src/model/contact_mechanics/contact_mechanics_model.cc
+++ b/src/model/contact_mechanics/contact_mechanics_model.cc
@@ -1,669 +1,669 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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,
+ Model::spatial_dimension, _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");
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 (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) {
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);
auto nb_quad_points = fem_boundary.getNbIntegrationPoints(type, ghost_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);
Array<Real> quad_coords(nb_elements * nb_quad_points, spatial_dimension);
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{type, 0, ghost_type};
for (auto el : element_ids) {
subelement.element = el;
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 & normal = *normals_iter;
auto ddot = inside_to_outside.dot(normal);
(*dual_iter) =
Matrix<Real>::Identity(spatial_dimension, spatial_dimension) *
normal;
if (ddot < 0) {
*dual_iter *= -1.0;
}
++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);
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 & field_name,
const std::string & group_name,
bool /*padding_flag*/) {
std::map<std::string, Array<bool> *> bool_nodal_fields;
bool_nodal_fields["blocked_dofs"] = blocked_dofs.get();
std::shared_ptr<dumpers::Field> field;
field = mesh.createNodalField(bool_nodal_fields[field_name], group_name);
return field;
}
/* -------------------------------------------------------------------------- */
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["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::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::ComputeIntFromEnum<ContactState>>();
field = mesh.createNodalField(this->contact_state.get(), group_name);
field =
dumpers::FieldComputeProxy::createFieldCompute(field, std::move(func));
}
return field;
}
/* -------------------------------------------------------------------------- */
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);
}
return size * nb_nodes_per_element;
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::packData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
const SynchronizationTag & /*tag*/) const {
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::unpackData(CommunicationBuffer & /*buffer*/,
const Array<Element> & /*elements*/,
const SynchronizationTag & /*tag*/) {}
/* -------------------------------------------------------------------------- */
Int ContactMechanicsModel::getNbData(const Array<Idx> & dofs,
const SynchronizationTag & /*tag*/) const {
UInt size = 0;
return size * dofs.size();
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::packData(CommunicationBuffer & /*buffer*/,
const Array<Idx> & /*dofs*/,
const SynchronizationTag & /*tag*/) const {
}
/* -------------------------------------------------------------------------- */
void ContactMechanicsModel::unpackData(CommunicationBuffer & /*buffer*/,
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 19198e481..7bfd64ae2 100644
--- a/src/model/contact_mechanics/contact_mechanics_model.hh
+++ b/src/model/contact_mechanics/contact_mechanics_model.hh
@@ -1,361 +1,361 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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<Idx>,
public BoundaryCondition<ContactMechanicsModel> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
public:
ContactMechanicsModel(
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
+ [[nodiscard]] 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>
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:
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;
Int getNbData(const Array<Idx> & dofs,
const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Idx> & dofs,
const SynchronizationTag & tag) const override;
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<bool> &);
/// 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<bool>> 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__ */
+#endif /* AKANTU_CONTACT_MECHANICS_MODEL_HH_ */
diff --git a/src/model/contact_mechanics/geometry_utils.hh b/src/model/contact_mechanics/geometry_utils.hh
index 25aa84d98..f1567d25e 100644
--- a/src/model/contact_mechanics/geometry_utils.hh
+++ b/src/model/contact_mechanics/geometry_utils.hh
@@ -1,148 +1,148 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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)
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
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
template <class Derived1, class Derived2, class Derived3, class Derived4,
class ElementList>
static Element 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 = 100, Real projection_tolerance = 1e-10,
Real extension_tolerance = 1e-5);
/// computes the natural projection on an element
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
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
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
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
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
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
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 Eigen::MatrixBase<Derived> & covariant_bases);
/// computes metric tensor with contravariant components
template <class Derived>
static Matrix<Real>
contravariantMetricTensor(const Eigen::MatrixBase<Derived> & covariant_bases);
// computes curvature tensor with convariant components
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
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"
+#include "geometry_utils_inline_impl.hh"
-#endif /* __AKANTU_GEOMETRY_UTILS_HH__ */
+#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.hh
similarity index 100%
rename from src/model/contact_mechanics/geometry_utils_inline_impl.cc
rename to src/model/contact_mechanics/geometry_utils_inline_impl.hh
diff --git a/src/model/contact_mechanics/resolution.cc b/src/model/contact_mechanics/resolution.cc
index c4a988ed7..e73851bdd 100644
--- a/src/model/contact_mechanics/resolution.cc
+++ b/src/model/contact_mechanics/resolution.cc
@@ -1,197 +1,199 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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);
assembleLocalToGlobalArray(element, local_fn, model.getNormalForce());
assembleLocalToGlobalArray(element, local_ft, model.getTangentialForce());
}
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) {
const auto master_conn = model.getMesh().getConnectivity(master);
Vector<Idx> elem_conn(master_conn.size() + 1);
elem_conn[0] = slave;
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 = global.getNbComponent();
auto nb_nodes = is_master_deformable ? connectivity.size() : 1;
Real alpha = is_master_deformable ? 0.5 : 1.;
MatrixProxy<Real> local_m(local.data(), nb_dofs, connectivity.size());
auto global_it = make_view(global, nb_dofs).begin();
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);
+ local_kn.zero();
computeNormalModuli(element, local_kn);
assembleLocalToGlobalMatrix(element, local_kn, global_stiffness);
Matrix<Real> local_kt(nb_nodes * spatial_dimension,
nb_nodes * spatial_dimension);
+ local_kt.zero();
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) {
const auto master_conn = model.getMesh().getConnectivity(master);
Vector<Idx> elem_conn(master_conn.size() + 1);
elem_conn[0] = slave;
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 (Int i : arange(connectivity.size())) {
UInt conn = connectivity[i];
for (Int j : arange(nb_dofs)) {
equations.push_back(conn * nb_dofs + j);
}
}
for (Int i : arange(total_nb_dofs)) {
UInt row = equations[i];
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 c80886348..1e2d4ecf4 100644
--- a/src/model/contact_mechanics/resolution.hh
+++ b/src/model/contact_mechanics/resolution.hh
@@ -1,217 +1,217 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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(const ContactElement & /*unused*/,
Vector<Real> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/// computes the tangential force vector due to frictional traction
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(const ContactElement & /*unused*/,
Matrix<Real> & /*unused*/) {
AKANTU_TO_IMPLEMENT();
}
/// compute the tangent moduli due to tangential traction
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
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 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) \
[](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__ */
+#endif /* AKANTU_RESOLUTION_HH_ */
diff --git a/src/model/contact_mechanics/resolution_utils.hh b/src/model/contact_mechanics/resolution_utils.hh
index bd8c79ef3..aa60b92fd 100644
--- a/src/model/contact_mechanics/resolution_utils.hh
+++ b/src/model/contact_mechanics/resolution_utils.hh
@@ -1,108 +1,108 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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
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__ */
+#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 feb374d0c..e258966da 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty.cc
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty.cc
@@ -1,604 +1,604 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(const Real & gap) const {
return epsilon_n * macaulay(gap);
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeNormalForce(const ContactElement & element,
Vector<Real> & force) {
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;
auto gap = gaps(element.slave);
auto && normal = normals.begin(spatial_dimension)[element.slave];
auto && projection = projections.begin(surface_dimension)[element.slave];
// compute normal traction
auto p_n = computeNormalTraction(gap) * nodal_area[element.slave];
auto shape_matrix =
ResolutionUtils::computeShapeFunctionMatrix(element, projection);
force = p_n * shape_matrix.transpose() * normal;
}
/* -------------------------------------------------------------------------- */
void ResolutionPenalty::computeTangentialForce(const ContactElement & element,
Vector<Real> & force) {
force.zero();
if (mu == 0) {
return;
}
auto surface_dimension = spatial_dimension - 1;
// compute covariant basis
auto && projection =
model.getProjections().begin(surface_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();
auto && tangential_traction =
tangential_tractions.begin(surface_dimension)[element.slave];
this->computeTangentialTraction(element, covariant_basis,
tangential_traction);
auto shape_matrix =
ResolutionUtils::computeShapeFunctionMatrix(element, projection);
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
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,
Eigen::MatrixBase<D> & traction_tangential) {
Int surface_dimension = spatial_dimension - 1;
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 = 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> & 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(current_tangent);
auto & previous_tangential_tractions = model.getPreviousTangentialTractions();
auto && previous_traction(
previous_tangential_tractions.begin(surface_dimension)[element.slave]);
auto & previous_tangents = model.getPreviousTangents();
auto && previous_tangent = previous_tangents.begin(
spatial_dimension, surface_dimension)[element.slave];
auto previous_contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(previous_tangent);
for (auto alpha : arange(surface_dimension)) {
for (auto gamma : arange(surface_dimension)) {
for (auto beta : arange(surface_dimension)) {
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];
auto coords = model.getMesh().extractNodalValuesFromElement(
model.getContactDetector().getPositions(), previous_element);
auto previous_real_projection = GeometryUtils::realProjection(
coords, previous_element, previous_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(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;
}
}
traction -= epsilon_t * covariant_metric_tensor * increment_xi;
}
/* -------------------------------------------------------------------------- */
template <typename D1, typename D2>
void ResolutionPenalty::computeStickTangentialTraction(
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,
Eigen::MatrixBase<D1> & traction_trial,
Eigen::MatrixBase<D2> & traction_tangential) {
UInt surface_dimension = spatial_dimension - 1;
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);
Real p_n = computeNormalTraction(gap);
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
auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// construct the main part of normal matrix
Matrix<Real> k_main(A.cols(), A.cols());
Matrix<Real> n_outer_n(spatial_dimension, spatial_dimension);
n_outer_n = normal * normal.transpose();
k_main =
(A.transpose() * n_outer_n * A) * epsilon_n * heaviside(gap) * nodal_area;
// construct the rotational part of the normal matrix
const auto & tangents = model.getTangents();
auto && covariant_basis(
tangents.begin(spatial_dimension, surface_dimension)[element.slave]);
auto contravariant_metric_tensor =
GeometryUtils::contravariantMetricTensor(covariant_basis);
// consists of 2 rotational parts
Matrix<Real> k_rot1(A.cols(), A.cols());
Matrix<Real> k_rot2(A.cols(), A.cols());
k_rot1.zero();
k_rot2.zero();
auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
projection);
for (auto && [alpha, tangent] : enumerate(covariant_basis)) {
auto n_outer_t = normal * tangent.transpose();
- // auto t_outer_n = tangent * normal.transpose();
+ auto t_outer_n = tangent * normal.transpose();
for (auto && [beta, Aj] : enumerate(Ajs)) {
// construct Aj from shape function wrt to jth natural
// coordinate
k_rot1 += (Aj.transpose() * n_outer_t * A) *
contravariant_metric_tensor(alpha, beta);
- k_rot2 += (A.transpose() * n_outer_t * Aj) *
+ k_rot2 += (A.transpose() * t_outer_n * 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
auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// computing shape derivatives
auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
projection);
// tangents should have been calculated in normal modulii
auto & tangents = model.getTangents();
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(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();
auto && tangential_traction =
tangential_tractions.begin(surface_dimension)[element.slave];
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)) {
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);
for (auto && values3 : enumerate(covariant_basis.transpose())) {
auto & theta = std::get<0>(values3);
auto & tangent_theta = std::get<1>(values3);
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]);
// 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
auto A = ResolutionUtils::computeShapeFunctionMatrix(element, projection);
// computing shape derivatives
auto Ajs = ResolutionUtils::computeDerivativeShapeFunctionMatrix(element,
projection);
// tangents should have been calculated in normal modulii
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(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
t_outer_n = tangent_beta * normal.transpose();
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 = tangent_alpha * tangent_beta.transpose();
k_second += (A.transpose() * t_outer_t * A) * epsilon_t * mu * p_n *
contravariant_metric_tensor(alpha, beta) / traction_norm *
nodal_area;
for (auto && values3 : enumerate(covariant_basis)) {
auto & gamma = std::get<0>(values3);
auto & tangent_gamma = std::get<1>(values3);
for (auto && values4 : enumerate(covariant_basis)) {
auto & theta = std::get<0>(values4);
auto & tangent_theta = std::get<1>(values4);
t_outer_t = tangent_gamma * tangent_theta.transpose();
// eq 107b
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
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 cc6526775..f703beb4e 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty.hh
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty.hh
@@ -1,128 +1,128 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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);
/// local computation of stiffness matrix due to slip state
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;
/// 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;
protected:
/// local computation of normal traction due to penetration
virtual Real computeNormalTraction(const Real & gap) const;
/// local computation of trial tangential traction due to friction
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
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
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
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__ */
+#endif /* AKANTU_RESOLUTION_PENALTY_HH_ */
diff --git a/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh b/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
index 8398a3b94..07c42f6d8 100644
--- a/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
+++ b/src/model/contact_mechanics/resolutions/resolution_penalty_quadratic.hh
@@ -1,55 +1,55 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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;
public:
/// local computation of tangent moduli due to normal traction
void computeNormalModuli(const ContactElement & element,
Matrix<Real> & stiffness) override;
protected:
/// local computation of normal traction due to penetration
Real computeNormalTraction(const Real & gap) const override;
};
} // namespace akantu
-#endif /* __AKANTU_RESOLUTION_PENALTY_QUADRATIC_HH__ */
+#endif /* AKANTU_RESOLUTION_PENALTY_QUADRATIC_HH_ */
diff --git a/src/model/contact_mechanics/surface_selector.hh b/src/model/contact_mechanics/surface_selector.hh
index 8102e0b32..11c177e74 100644
--- a/src/model/contact_mechanics/surface_selector.hh
+++ b/src/model/contact_mechanics/surface_selector.hh
@@ -1,139 +1,139 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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<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<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<Idx> & nodes_list,
const NewNodesEvent & event) override;
public:
Array<Idx> & getMasterList() override;
Array<Idx> & getSlaveList() override;
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<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<Int> & nodes_list,
const NewNodesEvent & event) override;
public:
Array<Idx> & getMasterList() override;
Array<Idx> & getSlaveList() override;
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<Idx> new_nodes_list;
};
#endif
} // namespace akantu
-#endif /* __AKANTU_SURFACE_SELECTOR_HH__ */
+#endif /* AKANTU_SURFACE_SELECTOR_HH_ */
diff --git a/src/model/diffusion_model/diffusion_law.cc b/src/model/diffusion_model/diffusion_law.cc
new file mode 100644
index 000000000..7b5ad1a4d
--- /dev/null
+++ b/src/model/diffusion_model/diffusion_law.cc
@@ -0,0 +1,167 @@
+#include "diffusion_law.hh"
+#include "heat_transfer_model.hh"
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+DiffusionLaw::DiffusionLaw(DiffusionModel & model, const ID & id,
+ const ID & fe_engine_id)
+ : Parent(model, id, model.getSpatialDimension(), _ek_regular, fe_engine_id),
+ grad_u(registerInternal("∇u", model.getSpatialDimension(), fe_engine_id)),
+ d_grad_u(
+ registerInternal("D∇u", model.getSpatialDimension(), fe_engine_id)),
+ diffusivity(registerInternal("diffusivity",
+ model.getSpatialDimension() *
+ model.getSpatialDimension(),
+ fe_engine_id)) {}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionLaw::computeGradU(ElementType type, GhostType ghost_type) {
+ if (grad_u.getRelease(type, ghost_type) != -1 and
+ grad_u.getRelease(type, ghost_type) ==
+ getHandler().getDiffusionRelease()) {
+ return;
+ }
+
+ auto & elem_filter = getElementFilter(type, ghost_type);
+ this->getFEEngine().gradientOnIntegrationPoints(
+ getHandler().getDiffusion(), grad_u(type, ghost_type), 1, type,
+ ghost_type, elem_filter);
+
+ grad_u.getRelease(type, ghost_type) = getHandler().getDiffusionRelease();
+}
+/* -------------------------------------------------------------------------- */
+void DiffusionLaw::computeDiffusivityGradU(GhostType ghost_type) {
+ auto dim = getHandler().getSpatialDimension();
+ for (auto && type : getElementFilter().elementTypes(dim, ghost_type)) {
+ this->computeGradU(type, ghost_type);
+ this->computeDiffusivityGradUOnQuadPoints(type, ghost_type);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionLaw::assembleInternalFlow(GhostType ghost_type) {
+ auto && model = this->getHandler();
+ auto dim = model.getSpatialDimension();
+ auto & fem = getFEEngine();
+
+ for (auto && type : getElementFilter().elementTypes(dim, ghost_type)) {
+ auto && elem_filter = getElementFilter(type, ghost_type);
+ auto nb_element = elem_filter.size();
+ if (nb_element == 0) {
+ return;
+ }
+
+ auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
+
+ auto & d_gradu_vect = d_grad_u(type, ghost_type);
+ auto nb_quad_points = d_grad_u.size();
+
+ Array<Real> bt_d_gu(nb_quad_points, nb_nodes_per_element);
+ fem.computeBtD(d_gradu_vect, bt_d_gu, type, ghost_type);
+
+ Array<Real> int_bt_d_gu(nb_element, nb_nodes_per_element);
+
+ fem.integrate(bt_d_gu, int_bt_d_gu, nb_nodes_per_element, type, ghost_type,
+ elem_filter);
+
+ model.getDOFManager().assembleElementalArrayLocalArray(
+ int_bt_d_gu, model.getInternalFlow(), type, ghost_type, -1,
+ elem_filter);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionLaw::assembleDiffusivityMatrix() {
+ auto & fem = this->getFEEngine();
+ auto & model = this->getHandler();
+
+ for (auto && type : getElementFilter().elementTypes(spatial_dimension)) {
+ auto && elem_filter = getElementFilter(type, _not_ghost);
+ auto nb_element = elem_filter.size();
+ if (nb_element == 0) {
+ return;
+ }
+ 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(diffusivity(type), *bt_d_b, 2, type, _not_ghost,
+ elem_filter);
+
+ /// 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, _not_ghost, elem_filter);
+
+ model.getDOFManager().assembleElementalMatricesToMatrix(
+ "K", model.getDOFName(), *K_e, type, _not_ghost, _symmetric,
+ elem_filter);
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+Int DiffusionLaw::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
+ AKANTU_DEBUG_IN();
+
+ Int size = 0;
+
+ switch (tag) {
+ case SynchronizationTag::_diffusion_gradient: {
+ // temperature gradient
+ size += getHandler().getNbIntegrationPoints(elements) * spatial_dimension *
+ Int(sizeof(Real));
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
+ }
+ }
+
+ AKANTU_DEBUG_OUT();
+ return size;
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionLaw::packData(CommunicationBuffer & buffer,
+ const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
+ switch (tag) {
+ case SynchronizationTag::_diffusion_gradient: {
+ packElementalDataHelper(this->grad_u, buffer, elements,
+ this->getFEEngine());
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionLaw::unpackData(CommunicationBuffer & buffer,
+ const Array<Element> & elements,
+ const SynchronizationTag & tag) {
+ switch (tag) {
+ case SynchronizationTag::_diffusion_gradient: {
+ unpackElementalDataHelper(grad_u, buffer, elements, getFEEngine());
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+DiffusionFactory & DiffusionLaw::getFactory() {
+ return DiffusionFactory::getInstance();
+}
+
+} // namespace akantu
diff --git a/src/model/diffusion_model/diffusion_law.hh b/src/model/diffusion_model/diffusion_law.hh
new file mode 100644
index 000000000..f7c4e2bac
--- /dev/null
+++ b/src/model/diffusion_model/diffusion_law.hh
@@ -0,0 +1,96 @@
+#include "constitutive_law.hh"
+
+#ifndef AKANTU_DIFFUSION_LAW_HH
+#define AKANTU_DIFFUSION_LAW_HH
+
+namespace akantu {
+class DiffusionModel;
+class DiffusionLaw;
+} // namespace akantu
+
+namespace akantu {
+
+using DiffusionFactory =
+ Factory<DiffusionLaw, ID, Int, const ID &, DiffusionModel &, const ID &>;
+
+/* -------------------------------------------------------------------------- */
+class DiffusionLaw : public ConstitutiveLaw<DiffusionModel> {
+ using Parent = ConstitutiveLaw<DiffusionModel>;
+
+public:
+ DiffusionLaw(DiffusionModel & model, const ID & id = "diffusion_law",
+ const ID & fe_engine_id = "");
+
+ virtual void assembleInternalFlow(GhostType ghost_type);
+ virtual void assembleDiffusivityMatrix();
+
+ virtual void computeGradU(ElementType type, GhostType ghost_type);
+
+ virtual void computeDiffusivityGradU(GhostType ghost_type = _not_ghost);
+ virtual void computeDiffusivityGradUOnQuadPoints(ElementType /*type*/,
+ GhostType /*ghost_type*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ virtual void computeDiffusivityOnQuadPoints(ElementType /*type*/,
+ GhostType /*ghost_type*/) {
+ AKANTU_TO_IMPLEMENT();
+ }
+
+ template <Int dim>
+ decltype(auto) getArguments(ElementType type, GhostType ghost_type) {
+ return zip("∇u"_n = make_view<dim>(grad_u(type, ghost_type)),
+ "D∇u"_n = make_view<dim>(d_grad_u(type, ghost_type)),
+ "diffusivity"_n =
+ make_view<dim, dim>(diffusivity(type, ghost_type)));
+ }
+
+ [[nodiscard]] virtual Real getStableTimeStep(Real /*element_size*/) {
+ return 0;
+ }
+
+ [[nodiscard]] virtual Real getRho() const { return 1; }
+
+ /* ------------------------------------------------------------------------ */
+ [[nodiscard]] 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;
+ /* ------------------------------------------------------------------------ */
+
+ /// static method to retrieve the diffusion factory
+ static DiffusionFactory & getFactory();
+
+protected:
+ InternalField<Real> & grad_u;
+ InternalField<Real> & d_grad_u;
+ InternalField<Real> & diffusivity;
+};
+
+namespace {
+ template <
+ template <Int> class Law, class Model_,
+ std::enable_if_t<std::is_base_of_v<DiffusionModel, Model_>> * = nullptr>
+ bool instantiateDiffusionLaw(const ID & id) {
+ return DiffusionFactory::getInstance().registerAllocator(
+ id,
+ [](Int dim, const ID & name, DiffusionModel & model, const ID & id) {
+ if (not aka::is_of_type<Model_>(model)) {
+ AKANTU_EXCEPTION("The diffusion law "
+ << name << " works only with model of type "
+ << debug::demangle(typeid(Model_).name()));
+ }
+ return tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) -> std::unique_ptr<DiffusionLaw> {
+ constexpr auto && dim_ = aka::decay_v<decltype(_)>;
+ return std::make_unique<Law<dim_>>(model, id);
+ },
+ dim);
+ });
+ }
+} // namespace
+
+} // namespace akantu
+#endif // AKANTU_DIFFUSION_LAW_HH
diff --git a/src/model/diffusion_model/diffusion_model.cc b/src/model/diffusion_model/diffusion_model.cc
new file mode 100644
index 000000000..27338c55f
--- /dev/null
+++ b/src/model/diffusion_model/diffusion_model.cc
@@ -0,0 +1,560 @@
+/**
+ * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * This file is part of Akantu
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You 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 "diffusion_law.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 diffusion {
+ namespace details {
+ class ComputeRhoFunctor {
+ public:
+ ComputeRhoFunctor(const DiffusionModel & model) : model(model){};
+
+ void operator()(Matrix<Real> & rho, const Element & element) {
+ auto law_id = model.getConstitutiveLawByElement()(element);
+ rho.array() = model.getConstitutiveLaw(law_id).getRho();
+ }
+
+ private:
+ const DiffusionModel & model;
+ };
+ } // namespace details
+} // namespace diffusion
+
+/* -------------------------------------------------------------------------- */
+DiffusionModel::DiffusionModel(Mesh & mesh, Int dim, const ID & id,
+ const std::shared_ptr<DOFManager> & dof_manager,
+ const ID & dof_name, ModelType model_type)
+ : Parent(mesh, model_type, dim, id), dof_name(dof_name) {
+ AKANTU_DEBUG_IN();
+
+ this->initDOFManager(dof_manager);
+
+ if (this->mesh.isDistributed()) {
+ auto & synchronizer = this->mesh.getElementSynchronizer();
+ this->registerSynchronizer(synchronizer, SynchronizationTag::_diffusion);
+ this->registerSynchronizer(synchronizer,
+ SynchronizationTag::_diffusion_gradient);
+ }
+
+ registerFEEngineObject<FEEngineType>(id + ":fem", mesh, spatial_dimension);
+
+ this->mesh.registerDumper<DumperParaview>(id, id, true);
+ this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular);
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+FEEngine & DiffusionModel::getFEEngineBoundary(const ID & name) {
+ return aka::as_type<FEEngine>(getFEEngineClassBoundary<FEEngineType>(name));
+}
+
+/* -------------------------------------------------------------------------- */
+MatrixType DiffusionModel::getMatrixType(const ID & matrix_id) const {
+ if (matrix_id == "K" or matrix_id == "M") {
+ return _symmetric;
+ }
+
+ return _mt_not_defined;
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleMatrix(const ID & matrix_id) {
+ if (matrix_id == "K") {
+ this->assembleDiffisivityMatrix();
+ } else if (matrix_id == "M" and need_to_reassemble_capacity) {
+ this->assembleCapacityMatrix();
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleLumpedMatrix(const ID & matrix_id) {
+ if (matrix_id == "M" and need_to_reassemble_capacity) {
+ this->assembleCapacityMatrixLumped();
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleResidual() {
+ this->assembleInternalFlow();
+
+ this->getDOFManager().assembleToResidual(dof_name, *this->external_flow, 1);
+ this->getDOFManager().assembleToResidual(dof_name, *this->internal_flow, 1);
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::predictor() { ++diffusion_release; }
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::corrector() { ++diffusion_release; }
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::initSolver(TimeStepSolverType time_step_solver_type,
+ NonLinearSolverType /*unused*/) {
+ DOFManager & dof_manager = this->getDOFManager();
+
+ this->allocNodalField(this->diffusion, 1, dof_name);
+ this->allocNodalField(this->external_flow, 1, "external_flow");
+ this->allocNodalField(this->internal_flow, 1, "internal_flow");
+ this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
+
+ if (not dof_manager.hasDOFs(dof_name)) {
+ dof_manager.registerDOFs(dof_name, *this->diffusion, _dst_nodal);
+ dof_manager.registerBlockedDOFs(dof_name, *this->blocked_dofs);
+ }
+
+ if (time_step_solver_type == TimeStepSolverType::_dynamic ||
+ time_step_solver_type == TimeStepSolverType::_dynamic_lumped) {
+ this->allocNodalField(this->diffusion_rate, 1, dof_name + "_rate");
+
+ if (not dof_manager.hasDOFsDerivatives(dof_name, 1)) {
+ dof_manager.registerDOFsDerivative(dof_name, 1, *this->diffusion_rate);
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+std::tuple<ID, TimeStepSolverType>
+DiffusionModel::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
+DiffusionModel::getDefaultSolverOptions(const TimeStepSolverType & type) const {
+ ModelSolverOptions options;
+
+ switch (type) {
+ case TimeStepSolverType::_dynamic_lumped: {
+ options.non_linear_solver_type = NonLinearSolverType::_lumped;
+ options.integration_scheme_type[dof_name] =
+ IntegrationSchemeType::_forward_euler;
+ options.solution_type[dof_name] = IntegrationScheme::_temperature_rate;
+ break;
+ }
+ case TimeStepSolverType::_static: {
+ options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
+ options.integration_scheme_type[dof_name] =
+ IntegrationSchemeType::_pseudo_time;
+ options.solution_type[dof_name] = 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[dof_name] =
+ IntegrationSchemeType::_forward_euler;
+ options.solution_type[dof_name] = IntegrationScheme::_temperature_rate;
+ } else {
+ options.non_linear_solver_type = NonLinearSolverType::_newton_raphson;
+ options.integration_scheme_type[dof_name] =
+ IntegrationSchemeType::_backward_euler;
+ options.solution_type[dof_name] = IntegrationScheme::_temperature;
+ }
+ break;
+ }
+ default:
+ AKANTU_EXCEPTION(type << " is not a valid time step solver type");
+ }
+
+ return options;
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleDiffisivityMatrix() {
+ AKANTU_DEBUG_ASSERT(this->getDOFManager().hasMatrix("K"),
+ "The K matrix has not been initialized yet.");
+
+ this->getDOFManager().zeroMatrix("K");
+
+ for_each_constitutive_law(
+ [](auto && diffusion_law) { diffusion_law.assembleDiffusivityMatrix(); });
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleInternalFlow() {
+ this->internal_flow->zero();
+
+ this->synchronize(SynchronizationTag::_diffusion);
+
+ for (auto ghost_type : ghost_types) {
+ for_each_constitutive_law([&](auto && diffusion_law) {
+ diffusion_law.computeDiffusivityGradU(ghost_type);
+ });
+
+ for_each_constitutive_law([&](auto && diffusion_law) {
+ diffusion_law.assembleInternalFlow(ghost_type);
+ });
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+auto DiffusionModel::getStableTimeStep() -> Real {
+ AKANTU_DEBUG_IN();
+
+ Real el_size{};
+ Real min_el_size = std::numeric_limits<Real>::max();
+
+ for (auto && type : mesh.elementTypes(spatial_dimension, _not_ghost)) {
+ 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);
+
+ for (auto && el_coord :
+ make_view(coord, spatial_dimension, nb_nodes_per_element)) {
+ el_size = FEEngine::getElementInradius(el_coord, type);
+ min_el_size = std::min(min_el_size, el_size);
+ }
+ }
+
+ Real min_dt = std::numeric_limits<Real>::max();
+ for_each_constitutive_law([&](auto && diffusion_law) {
+ min_dt = std::min(diffusion_law.getStableTimeStep(min_el_size), min_dt);
+ });
+
+ mesh.getCommunicator().allReduce(min_dt, SynchronizerOperation::_min);
+
+ AKANTU_DEBUG_OUT();
+
+ return min_dt;
+}
+/* -------------------------------------------------------------------------- */
+
+void DiffusionModel::setTimeStep(Real time_step, const ID & solver_id) {
+ Model::setTimeStep(time_step, solver_id);
+
+ this->mesh.getDumper(id).setTimeStep(time_step);
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleCapacityMatrixLumped() {
+ AKANTU_DEBUG_IN();
+
+ if (!this->getDOFManager().hasLumpedMatrix("M")) {
+ this->getDOFManager().getNewLumpedMatrix("M");
+ }
+
+ this->getDOFManager().zeroLumpedMatrix("M");
+
+ for (auto && ghost_type : ghost_types) {
+ auto & fem = getFEEngineClass<FEEngineType>();
+ diffusion::details::ComputeRhoFunctor compute_rho(*this);
+
+ for (auto && type :
+ mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
+ fem.assembleFieldLumped(compute_rho, "M", dof_name, this->getDOFManager(),
+ type, ghost_type);
+ }
+ }
+
+ need_to_reassemble_capacity_lumped = false;
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::assembleCapacityMatrix() {
+ AKANTU_DEBUG_IN();
+ auto ghost_type = _not_ghost;
+
+ this->getDOFManager().zeroMatrix("M");
+
+ auto & fem = getFEEngineClass<FEEngineType>();
+
+ diffusion::details::ComputeRhoFunctor rho_functor(*this);
+
+ for (auto && type :
+ mesh.elementTypes(spatial_dimension, ghost_type, _ek_regular)) {
+ fem.assembleFieldMatrix(rho_functor, "M", dof_name, this->getDOFManager(),
+ type, ghost_type);
+ }
+
+ need_to_reassemble_capacity = false;
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+auto DiffusionModel::computeThermalEnergyByNode() -> Real {
+ AKANTU_DEBUG_IN();
+ auto time_step = this->getTimeStep();
+ Real ethermal = 0.;
+
+ for (auto && [n, flow] :
+ enumerate(make_view(*internal_flow, internal_flow->getNbComponent()))) {
+ Real E = 0.;
+ bool count_node = mesh.isLocalOrMasterNode(n);
+
+ if (count_node) {
+ E += (flow.array() * time_step).sum();
+ }
+
+ ethermal += E;
+ }
+
+ mesh.getCommunicator().allReduce(ethermal, SynchronizerOperation::_sum);
+
+ AKANTU_DEBUG_OUT();
+ return ethermal;
+}
+
+/* -------------------------------------------------------------------------- */
+auto DiffusionModel::getEnergy(const ID & energy_id) -> Real {
+ AKANTU_DEBUG_IN();
+ Real energy = 0;
+
+ for_each_constitutive_law([&energy, &energy_id](auto && constitutive_law) {
+ energy += constitutive_law.getEnergy(energy_id);
+ });
+
+ // reduction sum over all processors
+ mesh.getCommunicator().allReduce(energy, SynchronizerOperation::_sum);
+
+ AKANTU_DEBUG_OUT();
+ return energy;
+}
+
+/* -------------------------------------------------------------------------- */
+auto DiffusionModel::getEnergy(const ID & energy_id, const Element & element)
+ -> Real {
+ auto constitutive_law_element = element;
+ constitutive_law_element.element =
+ this->getConstitutiveLawLocalNumbering()(element);
+
+ return this->getConstitutiveLaw(element).getEnergy(energy_id,
+ constitutive_law_element);
+}
+
+/* -------------------------------------------------------------------------- */
+std::shared_ptr<dumpers::Field>
+DiffusionModel::createNodalFieldBool(const std::string & field_name,
+ const std::string & group_name,
+ 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> DiffusionModel::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[dof_name] = diffusion.get();
+ real_nodal_fields[dof_name + "_rate"] = diffusion_rate.get();
+ real_nodal_fields["external_flow"] = external_flow.get();
+ real_nodal_fields["internal_flow"] = internal_flow.get();
+ real_nodal_fields["increment"] = increment.get();
+
+ if (auto it = real_nodal_fields.find(field_name);
+ it != real_nodal_fields.end()) {
+ return mesh.createNodalField(it->second, group_name);
+ }
+
+ return nullptr;
+}
+
+/* -------------------------------------------------------------------------- */
+std::shared_ptr<dumpers::Field> DiffusionModel::createElementalField(
+ const std::string & field_name, const std::string & group_name,
+ bool /*padding_flag*/, Int /*spatial_dimension*/,
+ ElementKind element_kind) {
+
+ std::shared_ptr<dumpers::Field> field;
+
+ if (field_name == "partitions") {
+ field = mesh.createElementalField<Int, dumpers::ElementPartitionField>(
+ mesh.getConnectivities(), group_name, this->spatial_dimension,
+ element_kind);
+ }
+ bool is_internal = this->isInternal(field_name, element_kind);
+
+ if (is_internal) {
+ auto nb_data_per_elem =
+ this->getInternalDataPerElem(field_name, element_kind);
+ auto & internal_flat = this->flattenInternal(field_name, element_kind);
+
+ field = mesh.createElementalField<Real, dumpers::InternalMaterialField>(
+ internal_flat, group_name, spatial_dimension, element_kind,
+ nb_data_per_elem);
+
+ // homogenize the field
+ auto foo = dumpers::HomogenizerProxy::createHomogenizer(*field);
+
+ field =
+ dumpers::FieldComputeProxy::createFieldCompute(field, std::move(foo));
+ };
+
+ return field;
+}
+
+/* -------------------------------------------------------------------------- */
+Int DiffusionModel::getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const {
+ AKANTU_DEBUG_IN();
+
+ Int size = 0;
+ auto nb_nodes = indexes.size();
+
+ switch (tag) {
+ case SynchronizationTag::_diffusion: {
+ size += nb_nodes * Int(sizeof(Real));
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
+ }
+ }
+
+ AKANTU_DEBUG_OUT();
+ return size;
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::packData(CommunicationBuffer & buffer,
+ const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const {
+ AKANTU_DEBUG_IN();
+
+ for (auto index : indexes) {
+ switch (tag) {
+ case SynchronizationTag::_diffusion: {
+ buffer << (*diffusion)(index);
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
+ }
+ }
+ }
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::unpackData(CommunicationBuffer & buffer,
+ const Array<Idx> & indexes,
+ const SynchronizationTag & tag) {
+ AKANTU_DEBUG_IN();
+
+ for (auto index : indexes) {
+ switch (tag) {
+ case SynchronizationTag::_diffusion: {
+ buffer >> (*diffusion)(index);
+ break;
+ }
+ default: {
+ AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
+ }
+ }
+ }
+
+ AKANTU_DEBUG_OUT();
+}
+
+/* -------------------------------------------------------------------------- */
+Int DiffusionModel::getNbData(const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
+ AKANTU_DEBUG_IN();
+
+ Int size = 0;
+ auto nb_nodes_per_element = 0;
+
+ for (auto && el : elements) {
+ nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
+ }
+
+ if (tag == SynchronizationTag::_diffusion) {
+ size += nb_nodes_per_element * Int(sizeof(Real)); // temperature
+ }
+
+ size += Parent::getNbData(elements, tag);
+
+ AKANTU_DEBUG_OUT();
+ return size;
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::packData(CommunicationBuffer & buffer,
+ const Array<Element> & elements,
+ const SynchronizationTag & tag) const {
+ if (tag == SynchronizationTag::_diffusion) {
+ packNodalDataHelper(*diffusion, buffer, elements, mesh);
+ }
+
+ Parent::packData(buffer, elements, tag);
+}
+
+/* -------------------------------------------------------------------------- */
+void DiffusionModel::unpackData(CommunicationBuffer & buffer,
+ const Array<Element> & elements,
+ const SynchronizationTag & tag) {
+ if (tag == SynchronizationTag::_diffusion) {
+ unpackNodalDataHelper(*diffusion, buffer, elements, mesh);
+ }
+
+ Parent::unpackData(buffer, elements, tag);
+}
+
+/* -------------------------------------------------------------------------- */
+} // namespace akantu
diff --git a/src/model/heat_transfer/heat_transfer_model.hh b/src/model/diffusion_model/diffusion_model.hh
similarity index 50%
rename from src/model/heat_transfer/heat_transfer_model.hh
rename to src/model/diffusion_model/diffusion_model.hh
index 2e9dc7574..0270b2183 100644
--- a/src/model/heat_transfer/heat_transfer_model.hh
+++ b/src/model/diffusion_model/diffusion_model.hh
@@ -1,297 +1,220 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
+#include "constitutive_laws_handler.hh"
#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_
+#ifndef AKANTU_DIFFUSION_MODEL_HH_
+#define AKANTU_DIFFUSION_MODEL_HH_
namespace akantu {
template <ElementKind kind, class IntegrationOrderFunctor>
class IntegratorGauss;
template <ElementKind kind> class ShapeLagrange;
+class DiffusionLaw;
} // namespace akantu
namespace akantu {
-class HeatTransferModel : public Model,
- public DataAccessor<Element>,
- public DataAccessor<Idx> {
+class DiffusionModel : public ConstitutiveLawsHandler<DiffusionLaw, Model> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
+ using Parent = ConstitutiveLawsHandler<DiffusionLaw, Model>;
+
public:
using FEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
- HeatTransferModel(Mesh & mesh, Int spatial_dimension = _all_dimensions,
- const ID & id = "heat_transfer_model",
- std::shared_ptr<DOFManager> dof_manager = nullptr);
-
- ~HeatTransferModel() override;
+ DiffusionModel(Mesh & mesh, Int dim = _all_dimensions,
+ const ID & id = "diffusion",
+ const std::shared_ptr<DOFManager> & dof_manager = nullptr,
+ const ID & dof_name = "diffusion",
+ ModelType model_type = ModelType::_heat_transfer_model);
/* ------------------------------------------------------------------------ */
/* 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;
+ void corrector() 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>
+ /// get the type of matrix needed
+ [[nodiscard]] MatrixType getMatrixType(const ID & matrix_id) const override;
+
+ [[nodiscard]] std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
- ModelSolverOptions
+ [[nodiscard]] ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
/* ------------------------------------------------------------------------ */
/* Methods for explicit */
/* ------------------------------------------------------------------------ */
public:
/// compute and get the stable time step
Real getStableTimeStep();
- /// set the stable timestep
+ /// set the stable time step
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();
+ void assembleDiffisivityMatrix();
/// assemble the conductivity matrix
- void assembleCapacity();
+ void assembleCapacityMatrix();
- /// compute the capacity on quadrature points
- void computeRho(Array<Real> & rho, ElementType type, GhostType ghost_type);
+ /// calculate the lumped capacity vector for heat transfer problem
+ void assembleCapacityMatrixLumped();
private:
+ /// compute the internal flow
+ void assembleInternalFlow();
+
/// 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 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 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<Idx> & indexes,
- const SynchronizationTag & tag) override;
+ [[nodiscard]] 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;
+
+ [[nodiscard]] Int getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const override;
+ void packData(CommunicationBuffer & buffer, const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const override;
+ void unpackData(CommunicationBuffer & buffer, 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,
Int spatial_dimension, ElementKind kind) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- 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_AUTO(TimeStep, time_step);
- /// get the assembled heat flux
- AKANTU_GET_MACRO_DEREF_PTR(InternalHeatRate, internal_heat_rate);
/// get the boundary vector
AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(BlockedDOFs, blocked_dofs);
/// get the external heat rate vector
- 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);
+ AKANTU_GET_MACRO_DEREF_PTR(ExternalFlow, external_flow);
+ /// get the external heat rate vector
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(ExternalFlow, external_flow);
+ /// get the assembled heat flux
+ AKANTU_GET_MACRO_DEREF_PTR(InternalFlow, internal_flow);
+ /// get the assembled heat flux
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(InternalFlow, internal_flow);
+ /// get the temperature
+ AKANTU_GET_MACRO_DEREF_PTR(Diffusion, diffusion);
/// get the temperature
- AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Temperature, temperature);
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(Diffusion, diffusion);
/// get the temperature derivative
- AKANTU_GET_MACRO_DEREF_PTR(TemperatureRate, temperature_rate);
+ AKANTU_GET_MACRO_DEREF_PTR(DiffusionRate, diffusion_rate);
+
+ AKANTU_GET_MACRO_AUTO(DOFName, dof_name);
+
+ AKANTU_GET_MACRO_AUTO(DiffusionRelease, diffusion_release);
/// get the energy denominated by thermal
- Real getEnergy(const std::string & energy_id, ElementType type, Idx index);
+ Real getEnergy(const ID & energy_id, const Element & element);
/// 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, Idx index);
- /// get the thermal energy for a given element
- Real getThermalEnergy();
+ Real getEnergy(const ID & energy_id);
protected:
/* ------------------------------------------------------------------------ */
FEEngine & getFEEngineBoundary(const ID & name = "") override;
- /* ----------------------------------------------------------------------- */
- 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;
+ ID dof_name;
/// temperatures array
- std::unique_ptr<Array<Real>> temperature;
+ std::unique_ptr<Array<Real>> diffusion;
/// temperatures derivatives array
- std::unique_ptr<Array<Real>> temperature_rate;
+ std::unique_ptr<Array<Real>> diffusion_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;
+ std::unique_ptr<Array<Real>> external_flow;
/// residuals array
- std::unique_ptr<Array<Real>> internal_heat_rate;
+ std::unique_ptr<Array<Real>> internal_flow;
/// 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};
- 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, Int> conductivity_release{{_not_ghost, 0},
- {_ghost, 0}};
+ Int diffusion_release{-1};
};
} // namespace akantu
-#endif /* AKANTU_HEAT_TRANSFER_MODEL_HH_ */
+#include "diffusion_law.hh"
+
+#endif /* AKANTU_DIFFUSION_MODEL_HH_ */
diff --git a/src/model/diffusion_model/heat_diffusion.cc b/src/model/diffusion_model/heat_diffusion.cc
new file mode 100644
index 000000000..1f721ff91
--- /dev/null
+++ b/src/model/diffusion_model/heat_diffusion.cc
@@ -0,0 +1,179 @@
+#include "heat_diffusion.hh"
+#include "heat_transfer_model.hh"
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+HeatDiffusion<dim>::HeatDiffusion(DiffusionModel & model, const ID & id,
+ const ID & fe_engine_id)
+ : DiffusionLaw(model, id, fe_engine_id) {
+ this->registerParam("density", density, _pat_parsmod);
+ 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);
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim> void HeatDiffusion<dim>::updateInternalParameters() {
+ Matrix<Real> tmp = conductivity.block<dim, dim>(0, 0);
+ conductivity = tmp;
+ this->diffusivity.set(conductivity);
+ Parent::updateInternalParameters();
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+void HeatDiffusion<dim>::computeDiffusivityGradUOnQuadPoints(
+ ElementType type, GhostType ghost_type) {
+ this->computeDiffusivityOnQuadPoints(type, ghost_type);
+
+ for (auto && args : getArguments(type, ghost_type)) {
+ const auto & C = args["diffusivity"_n];
+ const auto & BT = args["∇u"_n];
+ auto & k_BT = args["D∇u"_n];
+
+ k_BT = C * BT;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+void HeatDiffusion<dim>::computeDiffusivityOnQuadPoints(ElementType type,
+ GhostType ghost_type) {
+ auto temperature_release = this->getHandler().getDiffusionRelease();
+ auto & diffusivity_release = this->diffusivity.getRelease(type, ghost_type);
+ if (diffusivity_release != -1 and
+ diffusivity_release == temperature_release) {
+ return;
+ }
+
+ for (auto && type : getElementFilter().elementTypes(dim, ghost_type)) {
+ Array<Real> temperature_on_qpoints(0, 1);
+
+ // compute the temperature on quadrature points
+ this->getFEEngine().interpolateOnIntegrationPoints(
+ getHandler().getDiffusion(), temperature_on_qpoints, 1, type,
+ ghost_type, getElementFilter(type, ghost_type));
+
+ for (auto && [C, T] :
+ zip(make_view<dim, dim>(this->diffusivity(type, ghost_type)),
+ temperature_on_qpoints)) {
+ C = conductivity;
+
+ C.array() += conductivity_variation * (T - T_ref);
+ }
+ }
+
+ diffusivity_release = temperature_release;
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+Real HeatDiffusion<dim>::getStableTimeStep(Real element_size) {
+ Real conductivity_max{};
+ Vector<Real> ce;
+ conductivity.eig(ce);
+ for (auto c : ce) {
+ conductivity_max = std::max(c, conductivity_max);
+ }
+
+ Real min_dt = 2. * element_size * element_size / 4. * this->density *
+ capacity / conductivity_max;
+
+ return min_dt;
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+template <class iterator, class t_iterator>
+void HeatDiffusion<dim>::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;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+auto HeatDiffusion<dim>::getThermalEnergy(const Element & element) -> Real {
+ AKANTU_DEBUG_IN();
+
+ auto nb_quadrature_points =
+ getFEEngine().getNbIntegrationPoints(element.type);
+ Vector<Real> Eth_on_quarature_points(nb_quadrature_points);
+
+ Array<Real> temperature_interpolated(0, 1);
+ Array<Idx> filter(1, 1);
+ filter(0) = element.element;
+
+ this->getFEEngine().interpolateOnIntegrationPoints(
+ getHandler().getDiffusion(), temperature_interpolated, 1, element.type,
+ element.ghost_type, filter);
+
+ auto T_it = temperature_interpolated.begin();
+ auto T_end = T_it + nb_quadrature_points;
+
+ getThermalEnergy(Eth_on_quarature_points.data(), T_it, T_end);
+
+ return getFEEngine().integrate(Eth_on_quarature_points, element);
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim> auto HeatDiffusion<dim>::getThermalEnergy() -> Real {
+ Real Eth = 0;
+
+ auto & fem = getFEEngine();
+
+ for (auto && type : getElementFilter().elementTypes(dim, _not_ghost)) {
+ auto nb_element = getElementFilter(type).size();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type, _not_ghost);
+ Array<Real> Eth_per_quad(nb_element * nb_quadrature_points, 1);
+
+ Array<Real> temperature_interpolated(0, 1);
+ // compute the temperature on quadrature points
+ this->getFEEngine().interpolateOnIntegrationPoints(
+ getHandler().getDiffusion(), temperature_interpolated, 1, type,
+ _not_ghost, getElementFilter(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;
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim> Real HeatDiffusion<dim>::getEnergy(const ID & energy_id) {
+ if (energy_id == "thermal") {
+ return getThermalEnergy();
+ }
+
+ return Parent::getEnergy(energy_id);
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+Real HeatDiffusion<dim>::getEnergy(const ID & energy_id,
+ const Element & element) {
+ if (energy_id == "thermal") {
+ return getThermalEnergy(element);
+ }
+
+ return Parent::getEnergy(energy_id, element);
+}
+
+/* -------------------------------------------------------------------------- */
+template class HeatDiffusion<1>;
+template class HeatDiffusion<2>;
+template class HeatDiffusion<3>;
+
+const bool diffusion_law_is_alocated_heat_diffusion [[maybe_unused]] =
+ instantiateDiffusionLaw<HeatDiffusion, HeatTransferModel>("heat_diffusion");
+
+} // namespace akantu
diff --git a/src/model/diffusion_model/heat_diffusion.hh b/src/model/diffusion_model/heat_diffusion.hh
new file mode 100644
index 000000000..e413e5aaf
--- /dev/null
+++ b/src/model/diffusion_model/heat_diffusion.hh
@@ -0,0 +1,59 @@
+#include "diffusion_law.hh"
+
+#ifndef AKANTU_HEAT_DIFFUSION_HH
+#define AKANTU_HEAT_DIFFUSION_HH
+
+namespace akantu {
+
+template <Int dim> class HeatDiffusion : public DiffusionLaw {
+ using Parent = DiffusionLaw;
+
+public:
+ HeatDiffusion(DiffusionModel & model, const ID & id,
+ const ID & fe_engine_id = "");
+
+ void updateInternalParameters() override;
+ void computeDiffusivityGradUOnQuadPoints(ElementType type,
+ GhostType ghost_type) override;
+ void computeDiffusivityOnQuadPoints(ElementType type,
+ GhostType ghost_type) override;
+
+ decltype(auto) getArguments(ElementType type, GhostType ghost_type) {
+ return DiffusionLaw::getArguments<dim>(type, ghost_type);
+ }
+
+ [[nodiscard]] Real getStableTimeStep(Real element_size) override;
+
+ [[nodiscard]] Real getRho() const override { return density * capacity; }
+
+ [[nodiscard]] Real getEnergy(const ID & energy_id) override;
+ [[nodiscard]] Real getEnergy(const ID & energy_id,
+ const Element & element) override;
+
+private:
+ auto getThermalEnergy(const Element & element) -> Real;
+ auto getThermalEnergy() -> Real;
+
+ template <class iterator, class t_iterator>
+ void getThermalEnergy(iterator Eth, t_iterator T_it, t_iterator T_end) const;
+
+private:
+ Real density{0.};
+
+ /// capacity
+ Real capacity{0.};
+
+ // conductivity matrix
+ Matrix<Real> conductivity;
+
+ // linear variation of the conductivity (for temperature dependent
+ // conductivity)
+ Real conductivity_variation{0.};
+
+ // reference temperature for the interpretation of temperature variation
+ Real T_ref{0.};
+};
+
+} // namespace akantu
+
+#endif // AKANTU_HEAT_DIFFUSION_HH
diff --git a/src/model/diffusion_model/heat_transfer_model.hh b/src/model/diffusion_model/heat_transfer_model.hh
new file mode 100644
index 000000000..c5436e93f
--- /dev/null
+++ b/src/model/diffusion_model/heat_transfer_model.hh
@@ -0,0 +1,92 @@
+/**
+ * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * This file is part of Akantu
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Akantu. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* -------------------------------------------------------------------------- */
+#include "diffusion_model.hh"
+
+#ifndef AKANTU_HEAT_TRANSFER_MODEL_HH_
+#define AKANTU_HEAT_TRANSFER_MODEL_HH_
+
+namespace akantu {
+
+class HeatTransferModel : public DiffusionModel {
+public:
+ HeatTransferModel(Mesh & mesh, Int dim = _all_dimensions,
+ const ID & id = "heat_transfer",
+ const std::shared_ptr<DOFManager> & dof_manager = nullptr)
+ : DiffusionModel(mesh, dim, id, dof_manager, "temperature",
+ ModelType::_heat_transfer_model) {}
+
+ [[nodiscard]] Array<Real> & getTemperature() { return this->getDiffusion(); }
+ [[nodiscard]] const Array<Real> & getTemperature() const {
+ return this->getDiffusion();
+ }
+ [[nodiscard]] Int getTemperatureRelease() const {
+ return this->getDiffusionRelease();
+ }
+ [[nodiscard]] const Array<Real> & getTemperatureRate() const {
+ return this->getDiffusionRate();
+ }
+ [[nodiscard]] Array<Real> & getExternalHeatRate() {
+ return this->getExternalFlow();
+ }
+ [[nodiscard]] const Array<Real> & getExternalHeatRate() const {
+ return this->getExternalFlow();
+ }
+ [[nodiscard]] const Array<Real> & getInternalHeatRate() const {
+ return this->getInternalFlow();
+ }
+
+ std::shared_ptr<dumpers::Field>
+ createNodalFieldReal(const std::string & field_name,
+ const std::string & group_name,
+ bool padding_flag) override {
+
+ std::map<ID, ID> aliases{{"internal_heat_rate", "internal_flow"},
+ {"external_heat_rate", "external_flow"}};
+
+ if (auto it = aliases.find(field_name); it != aliases.end()) {
+ return DiffusionModel::createNodalFieldReal(it->second, group_name,
+ padding_flag);
+ }
+
+ return DiffusionModel::createNodalFieldReal(field_name, group_name,
+ padding_flag);
+ }
+
+ std::shared_ptr<dumpers::Field>
+ createElementalField(const std::string & field_name,
+ const std::string & group_name, bool padding_flag,
+ Int spatial_dimension, ElementKind kind) override {
+ std::map<ID, ID> aliases{{"conductivity", "diffusivity"}};
+
+ if (auto it = aliases.find(field_name); it != aliases.end()) {
+ return DiffusionModel::createElementalField(
+ it->second, group_name, padding_flag, spatial_dimension, kind);
+ }
+
+ return DiffusionModel::createElementalField(
+ field_name, group_name, padding_flag, spatial_dimension, kind);
+ }
+};
+
+} // namespace akantu
+
+#endif /* AKANTU_HEAT_TRANSFER_MODEL_HH_ */
diff --git a/src/model/heat_transfer/heat_transfer_model.cc b/src/model/heat_transfer/heat_transfer_model.cc
deleted file mode 100644
index 42def4c5a..000000000
--- a/src/model/heat_transfer/heat_transfer_model.cc
+++ /dev/null
@@ -1,866 +0,0 @@
-/**
- * Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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, 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);
- variation.fill(conductivity_variation * (T - T_ref));
- // @TODO: Guillaume are you sure ? why due you compute variation then ?
- 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 = 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)) {
- auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
-
- auto & k_gradt_on_qpoints_vect = k_gradt_on_qpoints(type, ghost_type);
-
- 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);
-
- 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();
-}
-
-/* -------------------------------------------------------------------------- */
-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 (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)) {
-
- 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);
- auto nb_element = mesh.getNbElement(type);
-
- 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();
- 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.data();
- // /// compute @f$ rho @f$ for each nodes of each element
- // 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();
-}
-
-/* -------------------------------------------------------------------------- */
-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 (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, 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;
- }
-}
-
-/* -------------------------------------------------------------------------- */
-auto HeatTransferModel::getThermalEnergy(ElementType type, Idx index) -> Real {
- AKANTU_DEBUG_IN();
-
- 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.data(), T_it, T_end);
-
- return getFEEngine().integrate(Eth_on_quarature_points,
- Element{type, index, _not_ghost});
-}
-
-/* -------------------------------------------------------------------------- */
-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;
-}
-
-/* -------------------------------------------------------------------------- */
-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;
-}
-
-/* -------------------------------------------------------------------------- */
-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*/, Int /*spatial_dimension*/,
- ElementKind element_kind) {
-
- std::shared_ptr<dumpers::Field> field;
-
- if (field_name == "partitions") {
- field = mesh.createElementalField<Int, dumpers::ElementPartitionField>(
- mesh.getConnectivities(), group_name, this->spatial_dimension,
- element_kind);
- } else if (field_name == "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") {
- 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 Int HeatTransferModel::getNbData(const Array<Idx> & indexes,
- const SynchronizationTag & tag) const {
- AKANTU_DEBUG_IN();
-
- 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<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<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 Int HeatTransferModel::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
- AKANTU_DEBUG_IN();
-
- 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/model b/src/model/model
new file mode 100644
index 000000000..cf3bc5f8b
--- /dev/null
+++ b/src/model/model
@@ -0,0 +1,2323 @@
+common/solver_callback.cc: this->sc_dof_manager = &dof_manager;
+common/non_local_toolbox/non_local_manager_inline_impl.hh: this->createNeighborhood(weight_func_id, neighborhood);
+common/non_local_toolbox/neighborhood_base.cc: spatial_dimension(this->model.getMesh().getSpatialDimension()) {
+common/non_local_toolbox/neighborhood_base.cc: this->registerDataAccessor(*this);
+common/non_local_toolbox/neighborhood_base.cc: this->createGrid();
+common/non_local_toolbox/neighborhood_base.cc: Mesh & mesh = this->model.getMesh();
+common/non_local_toolbox/neighborhood_base.cc: spacing.fill(this->neighborhood_radius * safety_factor);
+common/non_local_toolbox/neighborhood_base.cc: auto q1_coords = this->quad_coordinates.get(q1);
+common/non_local_toolbox/neighborhood_base.cc: auto q2_coords = this->quad_coordinates.get(q2);
+common/non_local_toolbox/neighborhood_base.cc: if (distance <= this->neighborhood_radius + Math::getTolerance() &&
+common/non_local_toolbox/neighborhood_base.cc: auto && coords = this->quad_coordinates.get(q);
+common/non_local_toolbox/neighborhood_base.cc: auto && q1_coords = this->quad_coordinates.get(q1);
+common/non_local_toolbox/neighborhood_base.cc: auto && q2_coords = this->quad_coordinates.get(q2);
+common/non_local_toolbox/neighborhood_base.cc: auto & fem = this->model.getFEEngine();
+common/non_local_toolbox/neighborhood_base.cc: for (auto && [q1, q2] : this->pair_list.at(ghost_type)) {
+common/non_local_toolbox/neighborhood_base.cc: this->grid_synchronizer->onElementsRemoved(element_list, new_numbering,
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: this->weight_function = std::make_unique<WeightFunction>(manager);
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: this->registerSubSection(ParserType::_weight_function, "weight_parameter",
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: this->weight_function->setRadius(this->neighborhood_radius);
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: this->non_local_manager.getVolumes();
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: auto && jacobians = this->non_local_manager.getJacobians();
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: auto && q1_coord = this->quad_coordinates.get(q1);
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: auto && q2_coord = this->quad_coordinates.get(q2);
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: weight(0) = q2_wJ * (*this->weight_function)(r, q1, q2);
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: weight(1) = q1_wJ * (*this->weight_function)(r, q2, q1);
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: if (this->weight_function->getUpdateRate() and
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: (this->non_local_manager.getNbStressCalls() %
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: this->weight_function->getUpdateRate() ==
+common/non_local_toolbox/non_local_neighborhood_tmpl.hh: this->computeWeights();
+common/non_local_toolbox/non_local_manager.cc: this->weight_function_types[name] = section;
+common/non_local_toolbox/non_local_manager.cc: this->callback = &callback;
+common/non_local_toolbox/non_local_manager.cc: volumes.initialize(this->model.getFEEngine(),
+common/non_local_toolbox/non_local_manager.cc: AKANTU_DEBUG_ASSERT(this->callback,
+common/non_local_toolbox/non_local_manager.cc: this->callback->insertIntegrationPointsInNeighborhoods(_not_ghost);
+common/non_local_toolbox/non_local_manager.cc: auto & mesh = this->model.getMesh();
+common/non_local_toolbox/non_local_manager.cc: this->createNeighborhoodSynchronizers();
+common/non_local_toolbox/non_local_manager.cc: this->callback->insertIntegrationPointsInNeighborhoods(_ghost);
+common/non_local_toolbox/non_local_manager.cc: FEEngine & fee = this->model.getFEEngine();
+common/non_local_toolbox/non_local_manager.cc: this->updatePairLists();
+common/non_local_toolbox/non_local_manager.cc: this->cleanupExtraGhostElements(); // nb_ghost_protected);
+common/non_local_toolbox/non_local_manager.cc: this->callback->initializeNonLocal();
+common/non_local_toolbox/non_local_manager.cc: this->setJacobians(fee, _ek_regular);
+common/non_local_toolbox/non_local_manager.cc: this->initNonLocalVariables();
+common/non_local_toolbox/non_local_manager.cc: this->computeWeights();
+common/non_local_toolbox/non_local_manager.cc: auto weight_func_it = this->weight_function_types.find(weight_func);
+common/non_local_toolbox/non_local_manager.cc: this->integration_points_positions,
+common/non_local_toolbox/non_local_manager.cc: Vector<Real> grid_center(this->spatial_dimension);
+common/non_local_toolbox/non_local_manager.cc: Vector<Real> spacing(this->spatial_dimension);
+common/non_local_toolbox/non_local_manager.cc: this->spatial_dimension, spacing, grid_center);
+common/non_local_toolbox/non_local_manager.cc: this->model.getMesh(), *dummy_grid,
+common/non_local_toolbox/non_local_manager.cc: std::string(this->id + ":" + neighborhood_id + ":grid_synchronizer"),
+common/non_local_toolbox/non_local_manager.cc: this->computeWeights();
+common/non_local_toolbox/non_local_manager.cc: this->updateWeightFunctionInternals();
+common/non_local_toolbox/non_local_manager.cc: this->volumes.zero();
+common/non_local_toolbox/non_local_manager.cc: this->model.getFEEngine(), _nb_component = spatial_dimension,
+common/non_local_toolbox/non_local_manager.cc: this->model.getFEEngine().computeIntegrationPointsCoordinates(
+common/non_local_toolbox/non_local_manager.cc: variable_name, nl_variable_name, this->id, nb_component);
+common/non_local_toolbox/non_local_manager.cc: auto it = this->weight_function_internals.find(field_name);
+common/non_local_toolbox/non_local_manager.cc: std::make_unique<ElementTypeMapReal>(field_name, this->id);
+common/non_local_toolbox/non_local_manager.cc: for (auto & pair : this->weight_function_internals) {
+common/non_local_toolbox/non_local_manager.cc: this->callback->updateLocalInternal(internals, ghost_type, _ek_regular);
+common/non_local_toolbox/non_local_manager.cc: variable.non_local.initialize(this->model.getFEEngine(),
+common/non_local_toolbox/non_local_manager.cc: this->callback->updateLocalInternal(variable.local, ghost_type,
+common/non_local_toolbox/non_local_manager.cc: this->volumes.zero();
+common/non_local_toolbox/non_local_manager.cc: this->averageInternals(_not_ghost);
+common/non_local_toolbox/non_local_manager.cc: this->averageInternals(_ghost);
+common/non_local_toolbox/non_local_manager.cc: this->callback->updateNonLocalInternal(variable.non_local, ghost_type,
+common/non_local_toolbox/non_local_manager.cc: this->callback->computeNonLocalContribution(_not_ghost);
+common/non_local_toolbox/non_local_manager.cc: ++this->compute_stress_calls;
+common/non_local_toolbox/non_local_manager.cc: FEEngine & fee = this->model.getFEEngine();
+common/non_local_toolbox/non_local_manager.cc: this->resizeElementTypeMap(1, volumes, model.getFEEngine());
+common/non_local_toolbox/non_local_manager.cc: this->resizeElementTypeMap(spatial_dimension, integration_points_positions,
+common/non_local_toolbox/non_local_manager.cc: auto & mesh = this->model.getMesh();
+common/non_local_toolbox/non_local_manager.cc: auto nb_quadrature_points = this->model.getNbIntegrationPoints(elements);
+common/non_local_toolbox/non_local_manager.cc: it->second->local, buffer, elements, this->model.getFEEngine());
+common/non_local_toolbox/non_local_manager.cc: it->second->local, buffer, elements, this->model.getFEEngine());
+common/non_local_toolbox/base_weight_function_inline_impl.hh: this->R2 = this->R * this->R;
+common/non_local_toolbox/base_weight_function_inline_impl.hh: this->R = radius;
+common/non_local_toolbox/base_weight_function_inline_impl.hh: this->R2 = this->R * this->R;
+common/non_local_toolbox/base_weight_function_inline_impl.hh: if (r <= this->R) {
+common/non_local_toolbox/base_weight_function_inline_impl.hh: Real alpha = (1. - r * r / this->R2);
+common/non_local_toolbox/non_local_neighborhood_base.cc: this->registerParam("radius", neighborhood_radius, 100.,
+common/non_local_toolbox/non_local_neighborhood_base.cc: this->is_creating_grid = true;
+common/non_local_toolbox/non_local_neighborhood_base.cc: this->grid_synchronizer = std::make_unique<GridSynchronizer>(
+common/non_local_toolbox/non_local_neighborhood_base.cc: this->model.getMesh(), *spatial_grid, *this,
+common/non_local_toolbox/non_local_neighborhood_base.cc: this->is_creating_grid = false;
+common/non_local_toolbox/non_local_neighborhood_base.cc: auto & pair_list = this->pair_list.at(ghost_type);
+common/non_local_toolbox/non_local_neighborhood_base.cc: auto & mesh = this->model.getMesh();
+common/non_local_toolbox/non_local_neighborhood_base.cc: this->non_local_variables.insert(id);
+common/non_local_toolbox/base_weight_function.hh: this->registerParam("update_rate", update_rate, Int(1), _pat_parsmod,
+common/non_local_toolbox/non_local_neighborhood_inline_impl.hh: size += this->non_local_manager.getNbData(elements, variable_id);
+common/non_local_toolbox/non_local_neighborhood_inline_impl.hh: size += this->weight_function->getNbData(elements, tag);
+common/non_local_toolbox/non_local_neighborhood_inline_impl.hh: this->non_local_manager.packData(buffer, elements, variable_id);
+common/non_local_toolbox/non_local_neighborhood_inline_impl.hh: this->weight_function->packData(buffer, elements, tag);
+common/non_local_toolbox/non_local_neighborhood_inline_impl.hh: this->non_local_manager.unpackData(buffer, elements, variable_id);
+common/non_local_toolbox/non_local_neighborhood_inline_impl.hh: this->weight_function->unpackData(buffer, elements, tag);
+common/non_local_toolbox/neighborhood_base_inline_impl.hh: this->spatial_grid->insert(quad, coords);
+common/non_linear_solver/non_linear_solver.cc: this->registerParam("type", this->non_linear_solver_type, _pat_parsable,
+common/non_linear_solver/non_linear_solver.cc: if (this->supported_type.find(this->non_linear_solver_type) ==
+common/non_linear_solver/non_linear_solver.cc: this->supported_type.end() and
+common/non_linear_solver/non_linear_solver.cc: this->non_linear_solver_type != NonLinearSolverType::_auto) {
+common/non_linear_solver/non_linear_solver.cc: << this->non_linear_solver_type
+common/non_linear_solver/non_linear_solver.cc: << this->id << "!");
+common/non_linear_solver/non_linear_solver.cc: this->_dof_manager.zeroResidual();
+common/non_linear_solver/non_linear_solver.cc: this->_dof_manager.assembleMatMulDOFsToResidual("K", -1.);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh: auto nb_quadrature_points = this->model.getNbIntegrationPoints(elements);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh: criterion, buffer, elements, this->model.getFEEngine());
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion_inline_impl.hh: criterion, buffer, elements, this->model.getFEEngine());
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->registerParam("radius", neighborhood_radius, 100.,
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: auto & mesh = this->model.getMesh();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: auto new_size = this->quad_coordinates(type, ghost_type).size();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->is_highest.alloc(new_size, 1, type, ghost_type, true);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->criterion.alloc(new_size, 1, type, ghost_type, 1.);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: auto new_size = this->quad_coordinates(type, ghost_type).size();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->criterion.alloc(new_size, 1, type, ghost_type, true);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->parseSection(section_neighborhood);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->createGrid();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->insertAllQuads(_not_ghost);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: auto & mesh = this->model.getMesh();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->createGridSynchronizer();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->insertAllQuads(_ghost);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->updatePairList();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->cleanupExtraGhostElements(nb_ghost_protected);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->is_creating_grid = true;
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->grid_synchronizer = std::make_unique<GridSynchronizer>(
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->model.getMesh(), *spatial_grid, *this, tags, sstr.str(), false);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->is_creating_grid = false;
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: Mesh & mesh = this->model.getMesh();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->model.getFEEngine().getNbIntegrationPoints(type, ghost_type);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: const Array<Real> & quads = this->quad_coordinates(type, ghost_type);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->is_highest.zero();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->criterion.zero();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->model.updateDataForNonLocalCriterion(criterion);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->asynchronousSynchronize(SynchronizationTag::_nh_criterion);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->waitEndSynchronize(SynchronizationTag::_nh_criterion);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: Mesh & mesh = this->model.getMesh();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->model.getFEEngine().getNbIntegrationPoints(type, _not_ghost);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: const Array<Real> & criterion_1 = this->criterion(lq1.type, lq1.ghost_type);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: const Array<Real> & criterion_2 = this->criterion(lq2.type, lq2.ghost_type);
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: auto & mesh = this->model.getMesh();
+common/non_local_toolbox/neighborhoods_criterion_evaluation/neighborhood_max_criterion.cc: this->onElementsRemoved(ghosts_to_erase, remove_elem.getNewNumbering(),
+common/non_linear_solver/non_linear_solver_lumped.cc: this->supported_type.insert(NonLinearSolverType::_lumped);
+common/non_linear_solver/non_linear_solver_lumped.cc: this->checkIfTypeIsSupported();
+common/non_linear_solver/non_linear_solver_lumped.cc: this->registerParam("b_a2x", this->alpha, 1., _pat_parsmod,
+common/non_linear_solver/non_linear_solver_lumped.cc: this->dof_manager.updateGlobalBlockedDofs();
+common/non_linear_solver/non_linear_solver_lumped.cc: auto & x = aka::as_type<SolverVectorDefault>(this->dof_manager.getSolution());
+common/non_linear_solver/non_linear_solver_lumped.cc: const auto & b = this->dof_manager.getResidual();
+common/non_linear_solver/non_linear_solver_lumped.cc: const auto & blocked_dofs = this->dof_manager.getBlockedDOFs();
+common/non_linear_solver/non_linear_solver_lumped.cc: const auto & A = this->dof_manager.getLumpedMatrix("M");
+common/non_linear_solver/non_linear_solver_lumped.cc: this->dof_manager.splitSolutionPerDOFs();
+common/non_linear_solver/non_linear_solver_linear.cc: this->supported_type.insert(NonLinearSolverType::_linear);
+common/non_linear_solver/non_linear_solver_linear.cc: this->checkIfTypeIsSupported();
+common/non_linear_solver/non_linear_solver_linear.cc: this->dof_manager.updateGlobalBlockedDofs();
+common/non_linear_solver/non_linear_solver_linear.cc: this->assembleResidual(solver_callback);
+common/non_linear_solver/non_linear_solver_linear.cc: this->solver->solve();
+common/non_linear_solver/non_linear_solver_linear.cc: this->assembleResidual(solver_callback);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->supported_type.insert(NonLinearSolverType::_newton_raphson_modified);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->supported_type.insert(NonLinearSolverType::_newton_raphson_contact);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->supported_type.insert(NonLinearSolverType::_newton_raphson);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->supported_type.insert(NonLinearSolverType::_linear);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->checkIfTypeIsSupported();
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("threshold", convergence_criteria, 1e-10, _pat_parsmod,
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("convergence_type", convergence_criteria_type,
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("max_iterations", max_iterations, 10, _pat_parsmod,
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("error", error, _pat_readable, "Last reached error");
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("nb_iterations", n_iter, _pat_readable,
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("converged", converged, _pat_readable,
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->registerParam("force_linear_recompute", force_linear_recompute, true,
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->dof_manager.updateGlobalBlockedDofs();
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->assembleResidual(solver_callback);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->non_linear_solver_type ==
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: (this->non_linear_solver_type == NonLinearSolverType::_linear &&
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->force_linear_recompute)) {
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->force_linear_recompute = false;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->n_iter = 0;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->converged = false;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->convergence_criteria_normalized = this->convergence_criteria;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->convergence_criteria_type == SolveConvergenceCriteria::_residual) {
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->converged = this->testConvergence(this->dof_manager.getResidual());
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->converged) {
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->convergence_criteria_normalized =
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->error * this->convergence_criteria;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->non_linear_solver_type == NonLinearSolverType::_newton_raphson or
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->non_linear_solver_type ==
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->solver->solve();
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->convergence_criteria_type ==
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->assembleResidual(solver_callback);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->converged = this->testConvergence(this->dof_manager.getResidual());
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->converged = this->testConvergence(this->dof_manager.getSolution());
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->convergence_criteria_type ==
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: not this->converged) {
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->assembleResidual(solver_callback);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->n_iter++;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: "[" << this->convergence_criteria_type << "] Convergence iteration "
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: << std::setw(std::log10(this->max_iterations)) << this->n_iter
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: << ": error " << this->error << (this->converged ? " < " : " > ")
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: << this->convergence_criteria_normalized);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: } while (not this->converged and this->n_iter <= this->max_iterations);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (this->convergence_criteria_type == SolveConvergenceCriteria::_solution) {
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->assembleResidual(solver_callback);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->converged =
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->converged and not(this->n_iter > this->max_iterations);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: solver_callback.afterSolveStep(this->converged);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: if (not this->converged) {
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->convergence_criteria, this->n_iter, this->error));
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: AKANTU_DEBUG_WARNING("[" << this->convergence_criteria_type
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: << std::setw(std::log10(this->max_iterations))
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: << this->n_iter << " iteration"
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: << (this->n_iter == 1 ? "" : "s") << "!");
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: const auto & blocked_dofs = this->dof_manager.getBlockedDOFs();
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: bool is_local_node = this->dof_manager.isLocalOrMasterDOF(n);
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: this->error = norm;
+common/non_linear_solver/non_linear_solver_newton_raphson.cc: return (error < this->convergence_criteria_normalized);
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: flags(this->axis) = true;
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: flags(this->axis) = true;
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: primal(this->axis) = value;
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: flags(this->axis) = true;
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: primal(this->axis) += value;
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: dual = this->bc_data * normals;
+common/boundary_condition/boundary_condition_functor_inline_impl.hh: dual = this->bc_data;
+common/boundary_condition/boundary_condition_functor.hh: inline void setIncrement(Real val) { this->value = val; }
+common/boundary_condition/boundary_condition_functor.hh: inline void setIncrement(const Vector<Real> & val) { this->value = val; }
+common/boundary_condition/boundary_condition_tmpl.hh: this->model = &model;
+common/boundary_condition/boundary_condition_tmpl.hh: this->primal = &primal;
+common/boundary_condition/boundary_condition_tmpl.hh: this->dual = &dual;
+common/boundary_condition/boundary_condition_tmpl.hh: this->initBC(model, primal, dual);
+common/boundary_condition/boundary_condition_tmpl.hh: this->primal_increment = &primal_increment;
+common/dof_manager/dof_manager.hh: return this->global_blocked_dofs_release !=
+common/dof_manager/dof_manager.hh: this->previous_global_blocked_dofs_release;
+common/dof_manager/dof_manager.hh: AKANTU_GET_MACRO_AUTO(SystemSize, this->system_size);
+common/dof_manager/dof_manager.hh: AKANTU_GET_MACRO_AUTO(LocalSystemSize, this->local_system_size);
+common/dof_manager/dof_manager.hh: AKANTU_GET_MACRO_AUTO(PureLocalSystemSize, this->pure_local_system_size);
+common/dof_manager/dof_manager.hh: ID non_linear_solver_id = this->id + ":nls:" + id;
+common/dof_manager/dof_manager.hh: return this->registerNonLinearSolver(non_linear_solver_id, nls);
+common/dof_manager/dof_manager.hh: ID time_step_solver_id = this->id + ":tss:" + id;
+common/dof_manager/dof_manager.hh: return this->registerTimeStepSolver(time_step_solver_id, tss);
+common/dof_manager/dof_manager.hh: ID matrix_id = this->id + ":mtx:" + id;
+common/dof_manager/dof_manager.hh: return this->registerSparseMatrix(matrix_id, sm);
+common/dof_manager/dof_manager.hh: ID matrix_id = this->id + ":mtx:" + id;
+common/dof_manager/dof_manager.hh: aka::as_type<MatType>(this->getMatrix(matrix_to_copy_id));
+common/dof_manager/dof_manager.hh: return this->registerSparseMatrix(matrix_id, sm);
+common/dof_manager/dof_manager.hh: ID matrix_id = this->id + ":lumped_mtx:" + id;
+common/dof_manager/dof_manager.hh: return this->registerLumpedMatrix(matrix_id, sm);
+common/dof_manager/dof_manager_inline_impl.hh: auto it = this->dofs.find(dof_id);
+common/dof_manager/dof_manager_inline_impl.hh: return it != this->dofs.end();
+common/dof_manager/dof_manager_inline_impl.hh: auto it = this->dofs.find(dof_id);
+common/dof_manager/dof_manager_inline_impl.hh: if (it == this->dofs.end()) {
+common/dof_manager/dof_manager_inline_impl.hh: << this->id);
+common/dof_manager/dof_manager_inline_impl.hh: auto it = this->dofs.find(dof_id);
+common/dof_manager/dof_manager_inline_impl.hh: if (it == this->dofs.end()) {
+common/dof_manager/dof_manager_inline_impl.hh: << this->id);
+common/dof_manager/dof_manager_inline_impl.hh: return aka::as_type<DOFData_>(this->getDOFData(dof_id));
+common/dof_manager/dof_manager_inline_impl.hh: return aka::as_type<DOFData_>(this->getDOFData(dof_id));
+common/dof_manager/dof_manager_inline_impl.hh: return *(this->getDOFData(dofs_id).dof);
+common/dof_manager/dof_manager_inline_impl.hh: return this->getDOFData(dofs_id).support_type;
+common/dof_manager/dof_manager_inline_impl.hh: return *(this->getDOFData(dofs_id).previous);
+common/dof_manager/dof_manager_inline_impl.hh: return (this->getDOFData(dofs_id).previous != nullptr);
+common/dof_manager/dof_manager_inline_impl.hh: return *(this->getDOFData(dofs_id).increment);
+common/dof_manager/dof_manager_inline_impl.hh: return (this->getDOFData(dofs_id).increment != nullptr);
+common/dof_manager/dof_manager_inline_impl.hh: auto & derivatives = this->getDOFData(dofs_id).dof_derivatives;
+common/dof_manager/dof_manager_inline_impl.hh: << this->id << " for dof "
+common/dof_manager/dof_manager_inline_impl.hh: const auto & derivatives = this->getDOFData(dofs_id).dof_derivatives;
+common/dof_manager/dof_manager_inline_impl.hh: return this->getDOFData(dofs_id).solution;
+common/dof_manager/dof_manager_inline_impl.hh: return this->getDOFData(dofs_id).solution;
+common/dof_manager/dof_manager_inline_impl.hh: return *(this->getDOFData(dofs_id).blocked_dofs);
+common/dof_manager/dof_manager_inline_impl.hh: return (this->getDOFData(dofs_id).blocked_dofs != nullptr);
+common/dof_manager/dof_manager_inline_impl.hh: auto dof_flag = this->dofs_flag(dof_num);
+common/dof_manager/dof_manager_inline_impl.hh: auto dof_flag = this->dofs_flag(dof_num);
+common/dof_manager/dof_manager_inline_impl.hh: auto dof_flag = this->dofs_flag(dof_num);
+common/dof_manager/dof_manager_inline_impl.hh: return this->global_equation_number(local);
+common/dof_manager/dof_manager_inline_impl.hh: auto it = this->global_to_local_mapping.find(global);
+common/dof_manager/dof_manager_inline_impl.hh: return (it != this->global_to_local_mapping.end());
+common/dof_manager/dof_manager_inline_impl.hh: auto it = this->global_to_local_mapping.find(global);
+common/dof_manager/dof_manager_inline_impl.hh: AKANTU_DEBUG_ASSERT(it != this->global_to_local_mapping.end(),
+common/dof_manager/dof_manager_inline_impl.hh: << global << " does not exists in " << this->id);
+common/dof_manager/dof_manager_inline_impl.hh: return this->dofs_flag(local_id);
+common/dof_manager/dof_manager_inline_impl.hh: const auto & dof_data = this->getDOFData(dof_id);
+common/dof_manager/dof_manager_inline_impl.hh: Vec tmp_array(aka::as_type<Vec>(*data_cache), this->id + ":tmp_array");
+common/dof_manager/dof_manager_inline_impl.hh: auto & dof_data = this->getDOFData(dof_id);
+common/dof_manager/dof_manager_inline_impl.hh: const auto & equation_number = this->getLocalEquationsNumbers(dof_id);
+common/dof_manager/dof_manager_inline_impl.hh: this->mesh->getElementGroup(dof_data.group_support)
+common/dof_manager/dof_manager_inline_impl.hh: nb_element = this->mesh->getNbElement(type, ghost_type);
+common/dof_manager/dof_manager_inline_impl.hh: const auto & connectivity = this->mesh->getConnectivity(type, ghost_type);
+common/dof_manager/dof_manager_inline_impl.hh: this->extractElementEquationNumber(equation_number, *conn_it,
+common/dof_manager/dof_manager_inline_impl.hh: return this->localToGlobalEquationNumber(local);
+common/dof_manager/dof_manager_inline_impl.hh: const auto & equation_number_m = this->getLocalEquationsNumbers(dof_id_m);
+common/dof_manager/dof_manager_inline_impl.hh: const auto & equation_number_n = this->getLocalEquationsNumbers(dof_id_n);
+common/dof_manager/dof_manager_inline_impl.hh: auto gi = this->localToGlobalEquationNumber(equation_number_m(term.i()));
+common/dof_manager/dof_manager_inline_impl.hh: auto gj = this->localToGlobalEquationNumber(equation_number_n(term.j()));
+common/dof_manager/dof_manager_default.cc: if (this->mesh->isDistributed()) {
+common/dof_manager/dof_manager_default.cc: this->synchronizer = std::make_unique<DOFSynchronizer>(
+common/dof_manager/dof_manager_default.cc: *this, this->id + ":dof_synchronizer");
+common/dof_manager/dof_manager_default.cc: auto & dof_data = this->getDOFDataTyped<DOFDataDefault>(dof_id);
+common/dof_manager/dof_manager_default.cc: this->mesh->getPeriodicNodeSynchronizer()
+common/dof_manager/dof_manager_default.cc: auto & dof_data = this->getDOFDataTyped<DOFDataDefault>(dof_id);
+common/dof_manager/dof_manager_default.cc: // scale_factor * (arr) * (not this->mesh->isPeriodicSlave(node));
+common/dof_manager/dof_manager_default.cc: if (this->synchronizer) {
+common/dof_manager/dof_manager_default.cc: this->synchronizer->registerDOFs(dof_id);
+common/dof_manager/dof_manager_default.cc: return this->registerSparseMatrix<SparseMatrixAIJ>(*this, id, matrix_type);
+common/dof_manager/dof_manager_default.cc: return this->registerSparseMatrix<SparseMatrixAIJ>(id, matrix_to_copy_id);
+common/dof_manager/dof_manager_default.cc: return this->registerLumpedMatrix<SolverVectorDefault>(*this, id);
+common/dof_manager/dof_manager_default.cc: return this->registerNonLinearSolver<NonLinearSolverNewtonRaphson>(
+common/dof_manager/dof_manager_default.cc: return this->registerNonLinearSolver<NonLinearSolverLinear>(*this, id,
+common/dof_manager/dof_manager_default.cc: return this->registerNonLinearSolver<NonLinearSolverLumped>(*this, id,
+common/dof_manager/dof_manager_default.cc: return this->registerTimeStepSolver<TimeStepSolverDefault>(
+common/dof_manager/dof_manager_default.cc: const auto & equation_number = this->getLocalEquationsNumbers(dof_id);
+common/dof_manager/dof_manager_default.cc: aka::as_type<SolverVectorArray>(this->getLumpedMatrix(A_id)).getVector();
+common/dof_manager/dof_manager_default.cc: auto & cache = aka::as_type<SolverVectorArray>(*this->data_cache);
+common/dof_manager/dof_manager_default.cc: this->assembleToGlobalArray(dof_id, x, cache.getVector(), scale_factor);
+common/dof_manager/dof_manager_default.cc: make_view(this->getResidualArray()))) {
+common/dof_manager/dof_manager_default.cc: this->addToProfile(matrix_id, dof_id, type, ghost_type);
+common/dof_manager/dof_manager_default.cc: const auto & dof_data = this->getDOFData(dof_id);
+common/dof_manager/dof_manager_default.cc: auto prof_it = this->matrix_profiled_dofs.find(mat_dof);
+common/dof_manager/dof_manager_default.cc: if (prof_it != this->matrix_profiled_dofs.end() &&
+common/dof_manager/dof_manager_default.cc: const auto & equation_number = this->getLocalEquationsNumbers(dof_id);
+common/dof_manager/dof_manager_default.cc: auto & A = this->getMatrix(matrix_id);
+common/dof_manager/dof_manager_default.cc: const auto & connectivity = this->mesh->getConnectivity(type, ghost_type);
+common/dof_manager/dof_manager_default.cc: this->mesh->getElementGroup(dof_data.group_support)
+common/dof_manager/dof_manager_default.cc: this->extractElementEquationNumber(
+common/dof_manager/dof_manager_default.cc: [&](auto & local) { return this->localToGlobalEquationNumber(local); });
+common/dof_manager/dof_manager_default.cc: this->matrix_profiled_dofs[mat_dof].push_back(type_pair);
+common/dof_manager/dof_manager_default.cc: return dynamic_cast<SolverVectorDefault *>(this->solution.get())->getVector();
+common/dof_manager/dof_manager_default.cc: return dynamic_cast<SolverVectorDefault *>(this->residual.get())->getVector();
+common/dof_manager/dof_manager_default.cc: return dynamic_cast<SolverVectorDefault *>(this->residual.get())->getVector();
+common/dof_manager/dof_manager_default.cc: if (this->synchronizer) {
+common/dof_manager/dof_manager_default.cc: this->synchronizer->onNodesAdded(nodes_list);
+common/dof_manager/dof_manager_default.cc: this->global_blocked_dofs.resize(this->local_system_size, 1);
+common/dof_manager/dof_manager_default.cc: this->previous_global_blocked_dofs.resize(this->local_system_size, 1);
+common/dof_manager/dof_manager_default.cc: if (this->global_blocked_dofs_release ==
+common/dof_manager/dof_manager_default.cc: this->previous_global_blocked_dofs_release) {
+common/dof_manager/dof_manager.cc: this->mesh->registerEventHandler(*this, _ehp_dof_manager);
+common/dof_manager/dof_manager.cc: for (const auto & dof_data : this->dofs) {
+common/dof_manager/dof_manager.cc: nb_element = this->mesh->getNbElement(type, ghost_type);
+common/dof_manager/dof_manager.cc: const auto & connectivity = this->mesh->getConnectivity(type, ghost_type);
+common/dof_manager/dof_manager.cc: Array<Real> array_localy_assembeled(this->mesh->getNbNodes(),
+common/dof_manager/dof_manager.cc: this->assembleElementalArrayLocalArray(
+common/dof_manager/dof_manager.cc: this->assembleToResidual(dof_id, array_localy_assembeled, 1);
+common/dof_manager/dof_manager.cc: Array<Real> array_localy_assembeled(this->mesh->getNbNodes(),
+common/dof_manager/dof_manager.cc: this->assembleElementalArrayLocalArray(
+common/dof_manager/dof_manager.cc: this->assembleToLumpedMatrix(dof_id, array_localy_assembeled, lumped_mtx, 1);
+common/dof_manager/dof_manager.cc: for (auto & pair : this->dofs) {
+common/dof_manager/dof_manager.cc: this->assembleMatMulVectToResidual(dof_id, A_id, *dof_data.dof,
+common/dof_manager/dof_manager.cc: for (auto && data : this->dofs) {
+common/dof_manager/dof_manager.cc: this->getSolutionPerDOFs(data.first, dof_data.solution);
+common/dof_manager/dof_manager.cc: this->getArrayPerDOFs(dof_id, this->getSolution(), solution_array);
+common/dof_manager/dof_manager.cc: this->getArrayPerDOFs(dof_id, this->getLumpedMatrix(lumped_mtx), lumped);
+common/dof_manager/dof_manager.cc: // this->makeConsistentForPeriodicity(dof_id, array_to_assemble);
+common/dof_manager/dof_manager.cc: this->assembleToGlobalArray(dof_id, array_to_assemble, this->getResidual(),
+common/dof_manager/dof_manager.cc: // this->makeConsistentForPeriodicity(dof_id, array_to_assemble);
+common/dof_manager/dof_manager.cc: auto & lumped = this->getLumpedMatrix(lumped_mtx);
+common/dof_manager/dof_manager.cc: this->assembleToGlobalArray(dof_id, array_to_assemble, lumped, scale_factor);
+common/dof_manager/dof_manager.cc: nb_pure_local += this->mesh->isLocalOrMasterNode(node);
+common/dof_manager/dof_manager.cc: nb_local_dofs -= this->mesh->isPeriodicSlave(node);
+common/dof_manager/dof_manager.cc: auto it = this->dofs.find(dof_id);
+common/dof_manager/dof_manager.cc: if (it != this->dofs.end()) {
+common/dof_manager/dof_manager.cc: std::unique_ptr<DOFData> dof_data_ptr = this->getNewDOFData(dof_id);
+common/dof_manager/dof_manager.cc: this->dofs[dof_id] = std::move(dof_data_ptr);
+common/dof_manager/dof_manager.cc: auto & dofs_storage = this->getNewDOFDataInternal(dof_id);
+common/dof_manager/dof_manager.cc: this->registerDOFsInternal(dof_id, dofs_array);
+common/dof_manager/dof_manager.cc: auto & dofs_storage = this->getNewDOFDataInternal(dof_id);
+common/dof_manager/dof_manager.cc: this->registerDOFsInternal(dof_id, dofs_array);
+common/dof_manager/dof_manager.cc: DOFData & dof_data = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: dofs_array.size() == this->mesh->getNbNodes(),
+common/dof_manager/dof_manager.cc: dof_data, this->mesh->getNbNodes(), [](auto && n) { return n; });
+common/dof_manager/dof_manager.cc: this->mesh->getElementGroup(group).getNodeGroup().getNodes();
+common/dof_manager/dof_manager.cc: this->pure_local_system_size += nb_pure_local;
+common/dof_manager/dof_manager.cc: this->local_system_size += nb_local_dofs;
+common/dof_manager/dof_manager.cc: this->system_size += nb_total_pure_local;
+common/dof_manager/dof_manager.cc: this->mesh->getElementGroup(group).getNodeGroup().getNodes();
+common/dof_manager/dof_manager.cc: this->updateDOFsData(
+common/dof_manager/dof_manager.cc: this->updateDOFsData(dof_data, nb_local_dofs, nb_pure_local,
+common/dof_manager/dof_manager.cc: this->updateDOFsData(dof_data, nb_local_dofs, nb_pure_local);
+common/dof_manager/dof_manager.cc: DOFData & dof = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: DOFData & dof = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: auto & dof = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: auto & dof = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: auto it = this->matrices.find(matrix_id);
+common/dof_manager/dof_manager.cc: if (it != this->matrices.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: this->matrices[matrix_id] = std::move(matrix);
+common/dof_manager/dof_manager.cc: auto it = this->lumped_matrices.find(matrix_id);
+common/dof_manager/dof_manager.cc: if (it != this->lumped_matrices.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: this->lumped_matrices[matrix_id] = std::move(matrix);
+common/dof_manager/dof_manager.cc: this->non_linear_solvers.find(non_linear_solver_id);
+common/dof_manager/dof_manager.cc: if (it != this->non_linear_solvers.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: this->non_linear_solvers[non_linear_solver_id] = std::move(non_linear_solver);
+common/dof_manager/dof_manager.cc: this->time_step_solvers.find(time_step_solver_id);
+common/dof_manager/dof_manager.cc: if (it != this->time_step_solvers.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: this->time_step_solvers[time_step_solver_id] = std::move(time_step_solver);
+common/dof_manager/dof_manager.cc: ID matrix_id = this->id + ":mtx:" + id;
+common/dof_manager/dof_manager.cc: SparseMatricesMap::const_iterator it = this->matrices.find(matrix_id);
+common/dof_manager/dof_manager.cc: if (it == this->matrices.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: ID mtx_id = this->id + ":mtx:" + id;
+common/dof_manager/dof_manager.cc: auto it = this->matrices.find(mtx_id);
+common/dof_manager/dof_manager.cc: return it != this->matrices.end();
+common/dof_manager/dof_manager.cc: ID matrix_id = this->id + ":lumped_mtx:" + id;
+common/dof_manager/dof_manager.cc: LumpedMatricesMap::const_iterator it = this->lumped_matrices.find(matrix_id);
+common/dof_manager/dof_manager.cc: if (it == this->lumped_matrices.end()) {
+common/dof_manager/dof_manager.cc: << matrix_id << " does not exists in " << this->id);
+common/dof_manager/dof_manager.cc: ID matrix_id = this->id + ":lumped_mtx:" + id;
+common/dof_manager/dof_manager.cc: auto it = this->lumped_matrices.find(matrix_id);
+common/dof_manager/dof_manager.cc: if (it == this->lumped_matrices.end()) {
+common/dof_manager/dof_manager.cc: << matrix_id << " does not exists in " << this->id);
+common/dof_manager/dof_manager.cc: ID mtx_id = this->id + ":lumped_mtx:" + id;
+common/dof_manager/dof_manager.cc: auto it = this->lumped_matrices.find(mtx_id);
+common/dof_manager/dof_manager.cc: return it != this->lumped_matrices.end();
+common/dof_manager/dof_manager.cc: ID non_linear_solver_id = this->id + ":nls:" + id;
+common/dof_manager/dof_manager.cc: this->non_linear_solvers.find(non_linear_solver_id);
+common/dof_manager/dof_manager.cc: if (it == this->non_linear_solvers.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: ID solver_id = this->id + ":nls:" + id;
+common/dof_manager/dof_manager.cc: auto it = this->non_linear_solvers.find(solver_id);
+common/dof_manager/dof_manager.cc: return it != this->non_linear_solvers.end();
+common/dof_manager/dof_manager.cc: ID time_step_solver_id = this->id + ":tss:" + id;
+common/dof_manager/dof_manager.cc: this->time_step_solvers.find(time_step_solver_id);
+common/dof_manager/dof_manager.cc: if (it == this->time_step_solvers.end()) {
+common/dof_manager/dof_manager.cc: << this->id);
+common/dof_manager/dof_manager.cc: ID time_step_solver_id = this->id + ":tss:" + solver_id;
+common/dof_manager/dof_manager.cc: auto it = this->time_step_solvers.find(time_step_solver_id);
+common/dof_manager/dof_manager.cc: return it != this->time_step_solvers.end();
+common/dof_manager/dof_manager.cc: this->getPreviousDOFs(dofs_id).copy(this->getDOFs(dofs_id));
+common/dof_manager/dof_manager.cc:void DOFManager::zeroResidual() { this->residual->zero(); }
+common/dof_manager/dof_manager.cc:void DOFManager::zeroMatrix(const ID & mtx) { this->getMatrix(mtx).zero(); }
+common/dof_manager/dof_manager.cc: this->getLumpedMatrix(mtx).zero();
+common/dof_manager/dof_manager.cc: auto & dof_data = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: this->pure_local_system_size += nb_new_pure_local;
+common/dof_manager/dof_manager.cc: this->local_system_size += nb_new_local_dofs;
+common/dof_manager/dof_manager.cc: this->system_size += nb_new_global;
+common/dof_manager/dof_manager.cc: this->residual->resize();
+common/dof_manager/dof_manager.cc: this->solution->resize();
+common/dof_manager/dof_manager.cc: this->data_cache->resize();
+common/dof_manager/dof_manager.cc: for (auto & pair : this->dofs) {
+common/dof_manager/dof_manager.cc: auto & dof_data = this->getDOFData(dof_id);
+common/dof_manager/dof_manager.cc: this->updateNodalDOFs(dof_id, nodes_list);
+common/dof_manager/dof_manager.cc: this->mesh->getElementGroup(group).getNodeGroup();
+common/dof_manager/dof_manager.cc: this->updateNodalDOFs(dof_id, new_nodes_list);
+common/dof_manager/dof_manager.cc: this->resizeGlobalArrays();
+common/dof_manager/dof_manager.cc: AKANTU_DEBUG_ASSERT(this->mesh != nullptr, "The `Mesh` pointer is not set.");
+common/dof_manager/dof_manager.cc: if (this->mesh->isDistributed() != this->residual->isDistributed()) {
+common/dof_manager/dof_manager.cc: << is_or_is_not(this->mesh->isDistributed())
+common/dof_manager/dof_manager.cc: << is_or_is_not(this->residual->isDistributed())
+common/dof_manager/dof_manager.cc: << debug::demangle(typeid(this->residual).name()) << ".");
+common/dof_manager/dof_manager.cc: this->communicator.exclusiveScan(nb_new_pure_local, offset);
+common/dof_manager/dof_manager.cc: auto first_global_dof_id = this->first_global_dof_id + offset;
+common/dof_manager/dof_manager.cc: auto first_local_dof_id = this->local_system_size - nb_new_local_dofs;
+common/dof_manager/dof_manager.cc: this->communicator.allReduce(offset);
+common/dof_manager/dof_manager.cc: this->first_global_dof_id += offset;
+common/dof_manager/dof_manager.cc: this->dofs_flag.resize(this->local_system_size, NodeFlag::_normal);
+common/dof_manager/dof_manager.cc: this->global_equation_number.resize(this->local_system_size, -1);
+common/dof_manager/dof_manager.cc: auto dof_flag = this->mesh->getNodeFlag(node);
+common/dof_manager/dof_manager.cc: auto is_local_dof = this->mesh->isLocalOrMasterNode(node);
+common/dof_manager/dof_manager.cc: auto is_periodic_slave = this->mesh->isPeriodicSlave(node);
+common/dof_manager/dof_manager.cc: auto is_periodic_master = this->mesh->isPeriodicMaster(node);
+common/dof_manager/dof_manager.cc: this->dofs_flag(local_eq_num) = dof_flag;
+common/dof_manager/dof_manager.cc: this->global_equation_number(local_eq_num) = first_global_dof_id;
+common/dof_manager/dof_manager.cc: this->global_to_local_mapping[first_global_dof_id] = local_eq_num;
+common/dof_manager/dof_manager.cc: this->global_equation_number(local_eq_num) = -1;
+common/dof_manager/dof_manager.cc: if (this->mesh->isPeriodic()) {
+common/dof_manager/dof_manager.cc: if (not this->mesh->isPeriodicSlave(node)) {
+common/dof_manager/dof_manager.cc: auto master_node = this->mesh->getPeriodicMaster(node);
+common/dof_manager/dof_manager.cc: if (this->mesh->isDistributed()) {
+common/dof_manager/dof_manager.cc: if (this->mesh->isPeriodic()) {
+common/dof_manager/dof_manager.cc: auto & node_synchronizer = this->mesh->getNodeSynchronizer();
+common/dof_manager/dof_manager.cc: this->dofs_flag.resize(this->local_system_size, NodeFlag::_normal);
+common/dof_manager/dof_manager.cc: this->global_equation_number.resize(this->local_system_size, -1);
+common/dof_manager/dof_manager.cc: this->dofs_flag(first_local_dof_id) = NodeFlag::_normal;
+common/dof_manager/dof_manager.cc: this->global_equation_number(first_local_dof_id) = first_global_dof_id;
+common/dof_manager/dof_manager.cc: this->global_to_local_mapping[first_global_dof_id] = first_local_dof_id;
+common/dof_manager/dof_manager.cc: this->previous_global_blocked_dofs.copy(this->global_blocked_dofs);
+common/dof_manager/dof_manager.cc: this->global_blocked_dofs.reserve(this->local_system_size, 0);
+common/dof_manager/dof_manager.cc: this->previous_global_blocked_dofs_release =
+common/dof_manager/dof_manager.cc: this->global_blocked_dofs_release;
+common/dof_manager/dof_manager.cc: if (not this->hasBlockedDOFs(pair.first)) {
+common/dof_manager/dof_manager.cc: this->global_blocked_dofs.push_back(dof);
+common/dof_manager/dof_manager.cc: std::sort(this->global_blocked_dofs.begin(), this->global_blocked_dofs.end());
+common/dof_manager/dof_manager.cc: auto last = std::unique(this->global_blocked_dofs.begin(),
+common/dof_manager/dof_manager.cc: this->global_blocked_dofs.end());
+common/dof_manager/dof_manager.cc: this->global_blocked_dofs.resize(last - this->global_blocked_dofs.begin());
+common/dof_manager/dof_manager.cc: ++this->global_blocked_dofs_release;
+common/dof_manager/dof_manager.cc: auto & J = this->getMatrix(matrix_id);
+common/dof_manager/dof_manager.cc: if (this->jacobian_release == J.getRelease()) {
+common/dof_manager/dof_manager.cc: if (this->hasBlockedDOFsChanged()) {
+common/dof_manager/dof_manager.cc: this->jacobian_release = J.getRelease();
+common/dof_manager/dof_manager.cc: this->previous_global_blocked_dofs_release =
+common/dof_manager/dof_manager.cc: this->global_blocked_dofs_release;
+common/dof_manager/dof_manager.cc: auto & A = this->getMatrix(A_id);
+common/dof_manager/dof_manager.cc: this->assembleToGlobalArray(dof_id, x, *data_cache, 1.);
+common/model_solver.hh: DOFManager & getDOFManager() { return *this->dof_manager; }
+common/constitutive_laws/constitutive_law_selector.hh: this->fallback_selector = fallback_selector;
+common/constitutive_laws/constitutive_law_selector.hh: this->fallback_selector = fallback_selector.shared_from_this();
+common/constitutive_laws/constitutive_law_selector.hh: return this->fallback_selector;
+common/constitutive_laws/constitutive_law_selector.hh: inline Idx getFallbackValue() const { return this->fallback_value; }
+common/constitutive_laws/constitutive_law_selector_tmpl.hh: auto && data = this->elementData(element);
+common/constitutive_laws/constitutive_law_selector_tmpl.hh: return this->model.getConstitutiveLawIndex(data);
+common/constitutive_laws/constitutive_law_tmpl.hh: return this->registerInternal<T, InternalFieldType>(
+common/constitutive_laws/constitutive_law_tmpl.hh: id, nb_component, this->default_fe_engine_id);
+common/constitutive_laws/constitutive_law_tmpl.hh: return this->registerInternal<T, InternalFieldType>(
+common/constitutive_laws/constitutive_law_tmpl.hh: id, nb_component, fe_engine_id, this->getElementFilter());
+common/constitutive_laws/constitutive_law_tmpl.hh: id, *this, this->spatial_dimension, fe_engine_id, element_filter));
+common/constitutive_laws/constitutive_law_tmpl.hh: if (auto it = this->internal_vectors.find(id);
+common/constitutive_laws/constitutive_law_tmpl.hh: auto && internal = this->template getInternal<T>(vect_id);
+common/constitutive_laws/constitutive_law_tmpl.hh: auto && internal = this->template getInternal<T>(vect_id);
+common/constitutive_laws/constitutive_law_tmpl.hh: this->getElementFilter().initialize(
+common/constitutive_laws/constitutive_law_tmpl.hh: this->initialize();
+common/constitutive_laws/constitutive_law_tmpl.hh: this->resizeInternals();
+common/constitutive_laws/constitutive_law_tmpl.hh: this->updateInternalParameters();
+common/constitutive_laws/constitutive_law_tmpl.hh: auto index = this->addElement(element);
+common/constitutive_laws/constitutive_law_tmpl.hh: this->resizeInternals();
+common/constitutive_laws/constitutive_law_tmpl.hh: this->removeIntegrationPoints(constitutive_law_local_new_numbering);
+common/constitutive_laws/constitutive_law_tmpl.hh: this->resizeInternals();
+common/constitutive_laws/constitutive_law_tmpl.hh: auto & law_indexes = this->handler.constitutive_law_index(type, gt);
+common/constitutive_laws/constitutive_law_tmpl.hh: this->handler.constitutive_law_local_numbering(type, gt);
+common/constitutive_laws/constitutive_law_tmpl.hh: auto nb_element = this->handler.getMesh().getNbElement(type, gt);
+common/constitutive_laws/constitutive_law_tmpl.hh: this->removeIntegrationPoints(constitutive_law_local_new_numbering);
+common/constitutive_laws/constitutive_law_tmpl.hh: auto law_index = handler.getConstitutiveLawIndex(this->name);
+common/constitutive_laws/constitutive_law_tmpl.hh: << this->name << std::endl);
+common/constitutive_laws/constitutive_law_tmpl.hh: global_element.element = this->getElementFilter()(local_element);
+common/constitutive_laws/constitutive_law_tmpl.hh: auto & el_filter = this->getElementFilter(element.type, element.ghost_type);
+common/constitutive_laws/constitutive_law_tmpl.hh: if (not this->template isInternal<T>(field_id, element_kind)) {
+common/constitutive_laws/constitutive_law_tmpl.hh: << id << " in the constitutive law " << this->name);
+common/constitutive_laws/constitutive_law_tmpl.hh: const auto & internal_field = this->template getInternal<T>(field_id);
+common/constitutive_laws/constitutive_law_tmpl.hh: if (!this->template isInternal<T>(field_id, element_kind)) {
+common/constitutive_laws/constitutive_law_tmpl.hh: << id << " in the constitutive law " << this->name);
+common/constitutive_laws/constitutive_law_tmpl.hh: const auto & internal_field = this->template getInternal<T>(field_id);
+common/constitutive_laws/constitutive_law_tmpl.hh: if (not this->template isInternal<T>(field_id, element_kind)) {
+common/constitutive_laws/constitutive_law_tmpl.hh: << this->name);
+common/constitutive_laws/constitutive_law_tmpl.hh: auto & internal_field = this->template getInternal<T>(field_id);
+common/constitutive_laws/constitutive_law_non_local_interface.hh: this->registerNeighborhood();
+common/constitutive_laws/constitutive_law_non_local_interface.hh: this->registerNonLocalVariables();
+common/constitutive_laws/constitutive_law_non_local_interface.hh: ID getNeighborhoodName() override { return this->name; }
+common/constitutive_laws/constitutive_laws_handler.hh: this->registerDataAccessor(*this);
+common/constitutive_laws/constitutive_laws_handler.hh: if (this->mesh.isDistributed()) {
+common/constitutive_laws/constitutive_laws_handler.hh: auto & synchronizer = this->mesh.getElementSynchronizer();
+common/constitutive_laws/constitutive_laws_handler.hh: this->registerSynchronizer(synchronizer,
+common/constitutive_laws/constitutive_laws_handler.hh: if (not this->parser.getLastParsedFile().empty()) {
+common/constitutive_laws/constitutive_laws_handler.hh: auto && [model_section, is_empty] = this->getParserSection();
+common/constitutive_laws/constitutive_laws_handler.hh: this->instantiateConstitutiveLaws(is_empty ? this->parser
+common/constitutive_laws/constitutive_laws_handler.hh: this->initConstitutiveLaws();
+common/constitutive_laws/constitutive_laws_handler.hh: return this->parser_type;
+common/constitutive_laws/constitutive_laws_handler.hh: this->constitutive_law_selector = constitutive_law_selector;
+common/constitutive_laws/internal_field.hh: this->spatial_dimension, ghost_type, this->element_kind);
+common/constitutive_laws/internal_field.hh: return this->element_filter.elementTypes(
+common/constitutive_laws/internal_field.hh: _spatial_dimension = this->spatial_dimension,
+common/constitutive_laws/internal_field.hh: _element_kind = this->element_kind, _ghost_type = ghost_type);
+common/constitutive_laws/internal_field.hh: return (this->element_filter(type, ghost_type));
+common/constitutive_laws/internal_field.hh: << this->getID() << " has not been activated");
+common/constitutive_laws/internal_field.hh: return this->previous_values->operator()(type, ghost_type);
+common/constitutive_laws/internal_field.hh: << this->getID() << " has not been activated");
+common/constitutive_laws/internal_field.hh: return this->previous_values->operator()(type, ghost_type);
+common/constitutive_laws/internal_field.hh: << this->getID() << " has not been activated");
+common/constitutive_laws/internal_field.hh: return *(this->previous_values);
+common/constitutive_laws/internal_field.hh: << this->getID() << " has not been activated");
+common/constitutive_laws/internal_field.hh: return *(this->previous_values);
+common/constitutive_laws/internal_field_tmpl.hh: this->internalInitialize(this->nb_component);
+common/constitutive_laws/internal_field_tmpl.hh: this->element_kind = element_kind;
+common/constitutive_laws/internal_field_tmpl.hh: new InternalField<T>("previous_" + this->getID(), *this));
+common/constitutive_laws/internal_field_tmpl.hh: if (not this->is_init) {
+common/constitutive_laws/internal_field_tmpl.hh: for (const auto & type : this->filterTypes(ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: if (this->exists(type, ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: old_sizes(type, ghost_type) = this->operator()(type, ghost_type).size();
+common/constitutive_laws/internal_field_tmpl.hh: for (const auto & type : this->elementTypes(ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: auto & vect = this->operator()(type, ghost_type);
+common/constitutive_laws/internal_field_tmpl.hh: this->setArrayValues(vect.data() + old_size * vect.getNbComponent(),
+common/constitutive_laws/internal_field_tmpl.hh: this->releases(type, ghost_type) += 1;
+common/constitutive_laws/internal_field_tmpl.hh: if (this->previous_values) {
+common/constitutive_laws/internal_field_tmpl.hh: this->previous_values->resize();
+common/constitutive_laws/internal_field_tmpl.hh: this->default_value = value;
+common/constitutive_laws/internal_field_tmpl.hh: this->reset();
+common/constitutive_laws/internal_field_tmpl.hh: for (const auto & type : this->elementTypes(ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: this->setArrayValues(vect.data(),
+common/constitutive_laws/internal_field_tmpl.hh: this->releases(type, ghost_type) += 1;
+common/constitutive_laws/internal_field_tmpl.hh: if (not this->is_init) {
+common/constitutive_laws/internal_field_tmpl.hh: this->nb_component = nb_component;
+common/constitutive_laws/internal_field_tmpl.hh: this->is_init = true;
+common/constitutive_laws/internal_field_tmpl.hh: for (const auto & type : this->filterTypes(ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: this->releases(type, ghost_type) = -1;
+common/constitutive_laws/internal_field_tmpl.hh: this->reset();
+common/constitutive_laws/internal_field_tmpl.hh: if (this->previous_values) {
+common/constitutive_laws/internal_field_tmpl.hh: this->previous_values->internalInitialize(nb_component);
+common/constitutive_laws/internal_field_tmpl.hh: *begin = this->default_value;
+common/constitutive_laws/internal_field_tmpl.hh: AKANTU_DEBUG_ASSERT(this->previous_values != nullptr,
+common/constitutive_laws/internal_field_tmpl.hh: << this->getID() << " has not been activated");
+common/constitutive_laws/internal_field_tmpl.hh: if (not this->is_init) {
+common/constitutive_laws/internal_field_tmpl.hh: for (const auto & type : this->elementTypes(ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: (*this->previous_values)(type, ghost_type)
+common/constitutive_laws/internal_field_tmpl.hh: AKANTU_DEBUG_ASSERT(this->previous_values != nullptr,
+common/constitutive_laws/internal_field_tmpl.hh: << this->getID() << " has not been activated");
+common/constitutive_laws/internal_field_tmpl.hh: if (not this->is_init) {
+common/constitutive_laws/internal_field_tmpl.hh: for (const auto & type : this->elementTypes(ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: .copy((*this->previous_values)(type, ghost_type));
+common/constitutive_laws/internal_field_tmpl.hh: if (not this->exists(type, ghost_type)) {
+common/constitutive_laws/internal_field_tmpl.hh: stream << "InternalField [ " << this->getID();
+common/constitutive_laws/internal_field_tmpl.hh: stream << " {" << this->getData(_not_ghost).size() << " types - "
+common/constitutive_laws/internal_field_tmpl.hh: << this->getData(_ghost).size() << " ghost types"
+common/constitutive_laws/constitutive_law.hh: this->element_filter =
+common/constitutive_laws/constitutive_law.hh: return this->getElementFilter().elementTypes(std::forward<pack>(_pack)...);
+common/constitutive_laws/random_internal_field_tmpl.hh: this->internalInitialize(nb_component);
+common/constitutive_laws/random_internal_field_tmpl.hh: this->reset();
+common/constitutive_laws/random_internal_field_tmpl.hh: this->reset();
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: auto & neighborhood = this->getModel().getNonLocalManager().getNeighborhood(
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: this->getNeighborhoodName());
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: this->getElementFilter().elementTypes(dim, ghost_type, _ek_regular)) {
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: const auto & elem_filter = this->getElementFilter(type, ghost_type);
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: auto nb_quad = this->getFEEngine().getNbIntegrationPoints(type, ghost_type);
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: this->getElementFilter().elementTypes(dim, ghost_type, kind)) {
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: this->template getInternal<Real>(field_id)(el_type, ghost_type);
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: const auto & filter = this->getElementFilter(el_type, ghost_type);
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: this->getFEEngine().getNbIntegrationPoints(el_type, ghost_type);
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: ID name = this->getNeighborhoodName();
+common/constitutive_laws/constitutive_law_non_local_interface_tmpl.hh: this->handler.getNonLocalManager().registerNeighborhood(name, name);
+common/constitutive_laws/random_internal_field.hh: return aka::as_type<RandomInternalField>(this->shared_from_this());
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "The model " << this->id << " has no constitutive_law named " << name);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "The model " << this->id
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "The model " << this->id
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "The model " << this->id << " has no constitutive_law named " << name);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "The model " << this->id << " has no constitutive_law named " << name);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->splitElementByConstitutiveLaw(elements, elements_per_cl);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: auto && cl = this->registerNewConstitutiveLaw(cl_name, cl_type, opt_param);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: sstr_cl << this->id << ":" << cl_count << ":" << cl_type;
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: cl_type, this->spatial_dimension, opt_param,
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: parser_section.getSubSections(this->parser_type);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->registerNewConstitutiveLaw(section);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->non_local_manager = std::make_unique<NonLocalManager>(
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: *this, *this, this->id + ":non_local_manager");
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "No constitutive_laws where instantiated for the model " << this->id);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->mesh,
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->mesh,
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->synchronize(SynchronizationTag::_constitutive_law_id);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->assignConstitutiveLawToElements();
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->synchronize(SynchronizationTag::_clh_init_cl);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: if (this->non_local_manager) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->non_local_manager->initialize();
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: for_each_element(this->mesh, [&](auto && element) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->non_local_manager->synchronize(
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: "quadrature_points_coordinates_tmp_nl", this->id);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: fe_engine, _nb_component = this->spatial_dimension,
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->spatial_dimension, ghost_type)) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: cl_el.element = this->constitutive_law_local_numbering(el);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: auto cl_id = this->constitutive_law_index(el);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->constitutive_law_index.initialize(
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->mesh, _element_kind = _ek_not_defined, _with_nb_element = true,
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->constitutive_law_local_numbering.initialize(
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->mesh, _element_kind = _ek_not_defined, _with_nb_element = true,
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: ElementTypeMapArray<Idx> filter("new_element_filter", this->id);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: if (this->mesh.getSpatialDimension(elem.type) != this->spatial_dimension) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->assignConstitutiveLawToElements(&filter);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: if (!(this->isInternal(field_name, element_kind))) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: auto it = this->registered_internals.find(key);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: if (it == this->registered_internals.end()) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: std::make_unique<ElementTypeMapArray<T>>(field_name, this->id);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->registered_internals[key] = std::move(internal);
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->mesh.elementTypes(this->spatial_dimension, ghost_type, kind)) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: for (auto & internal : this->registered_internals) {
+common/constitutive_laws/constitutive_laws_handler_tmpl.hh: this->flattenInternal(_id, kind);
+common/model_solver.cc: std::string name = section.getParameter("name", this->id);
+common/model_solver.cc: return type == model_type and name == this->id;
+common/model_solver.cc: this->dof_manager = dof_manager;
+common/model_solver.cc: this->setDOFManager(*this->dof_manager);
+common/model_solver.cc: return this->dof_manager;
+common/model_solver.cc: auto && [section, is_empty] = this->getParserSection();
+common/model_solver.cc: return this->initDOFManager(section, solver_type);
+common/model_solver.cc: return this->initDOFManager(solver_type);
+common/model_solver.cc: this->dof_manager = DOFManagerFactory::getInstance().allocate(
+common/model_solver.cc: solver_type, mesh, this->id + ":dof_manager_" + solver_type);
+common/model_solver.cc: this->setDOFManager(*this->dof_manager);
+common/model_solver.cc: return this->dof_manager;
+common/model_solver.cc: this->initDOFManager(solver_type);
+common/model_solver.cc: auto tss_options = this->getDefaultSolverOptions(tss_type);
+common/model_solver.cc: this->getNewSolver(solver_id, tss_type, nls_type);
+common/model_solver.cc: this->dof_manager->getNonLinearSolver(solver_id).parseSection(
+common/model_solver.cc: this->setIntegrationScheme(solver_id, dof_id, it_type, s_type);
+common/model_solver.cc: if (!this->hasIntegrationScheme(solver_id, is_type.first)) {
+common/model_solver.cc: this->setIntegrationScheme(solver_id, is_type.first, is_type.second,
+common/model_solver.cc: if (this->hasSolver(default_solver)) {
+common/model_solver.cc: this->setDefaultSolver(default_solver);
+common/model_solver.cc: return this->dof_manager;
+common/model_solver.cc: tmp_solver_id = this->default_solver_id;
+common/model_solver.cc: TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(tmp_solver_id);
+common/model_solver.cc: tmp_solver_id = this->default_solver_id;
+common/model_solver.cc: this->dof_manager->getTimeStepSolver(tmp_solver_id);
+common/model_solver.cc: return this->getSolver(solver_id);
+common/model_solver.cc: return this->getSolver(solver_id);
+common/model_solver.cc: return this->getSolver(solver_id).getNonLinearSolver();
+common/model_solver.cc: return this->getSolver(solver_id).getNonLinearSolver();
+common/model_solver.cc: tmp_solver_id = this->default_solver_id;
+common/model_solver.cc: if (not this->dof_manager) {
+common/model_solver.cc: return this->dof_manager->hasTimeStepSolver(tmp_solver_id);
+common/model_solver.cc: this->hasSolver(solver_id),
+common/model_solver.cc: this->default_solver_id = solver_id;
+common/model_solver.cc: TimeStepSolver & tss = this->getSolver(solver_id);
+common/model_solver.cc: if (this->default_solver_id.empty()) {
+common/model_solver.cc: this->default_solver_id = solver_id;
+common/model_solver.cc: this->initSolver(time_step_solver_type, non_linear_solver_type);
+common/model_solver.cc: NonLinearSolver & nls = this->dof_manager->getNewNonLinearSolver(
+common/model_solver.cc: this->dof_manager->getNewTimeStepSolver(solver_id, time_step_solver_type, nls,
+common/model_solver.cc: const TimeStepSolver & tss = this->getSolver(solver_id);
+common/model_solver.cc: TimeStepSolver & tss = this->getSolver(solver_id);
+common/model_solver.cc: TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id);
+common/model_solver.cc: TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id);
+common/model_solver.cc: return (not this->default_solver_id.empty());
+common/model_solver.cc: TimeStepSolver & tss = this->dof_manager->getTimeStepSolver(solver_id);
+common/integration_scheme/pseudo_time.cc: auto & us = this->dof_manager.getDOFs(this->dof_id);
+common/integration_scheme/pseudo_time.cc: const auto & deltas = this->dof_manager.getSolution(this->dof_id);
+common/integration_scheme/pseudo_time.cc: const auto & blocked_dofs = this->dof_manager.getBlockedDOFs(this->dof_id);
+common/integration_scheme/pseudo_time.cc: SparseMatrix & J = this->dof_manager.getMatrix("J");
+common/integration_scheme/pseudo_time.cc: const SparseMatrix & K = this->dof_manager.getMatrix("K");
+common/integration_scheme/pseudo_time.cc: does_j_need_update |= this->dof_manager.hasBlockedDOFsChanged();
+common/integration_scheme/generalized_trapezoidal.cc: this->registerParam("alpha", this->alpha, alpha, _pat_parsmod,
+common/integration_scheme/generalized_trapezoidal.cc: this->allCorrector<_temperature>(delta_t, u, u_dot, blocked_dofs, delta);
+common/integration_scheme/generalized_trapezoidal.cc: this->allCorrector<_temperature_rate>(delta_t, u, u_dot, blocked_dofs,
+common/integration_scheme/generalized_trapezoidal.cc: SparseMatrix & J = this->dof_manager.getMatrix("J");
+common/integration_scheme/generalized_trapezoidal.cc: const SparseMatrix & M = this->dof_manager.getMatrix("M");
+common/integration_scheme/generalized_trapezoidal.cc: const SparseMatrix & K = this->dof_manager.getMatrix("K");
+common/integration_scheme/generalized_trapezoidal.cc: does_j_need_update |= this->dof_manager.hasBlockedDOFsChanged();
+common/integration_scheme/generalized_trapezoidal.cc: Real d = this->getTemperatureRateCoefficient(type, delta_t);
+common/integration_scheme/generalized_trapezoidal.cc: Real e = this->getTemperatureCoefficient(type, delta_t);
+common/time_step_solvers/time_step_solver_default.cc: this->is_mass_lumped = true;
+common/time_step_solvers/time_step_solver_default.cc: if (this->is_mass_lumped) {
+common/time_step_solvers/time_step_solver_default.cc: if (this->integration_schemes.find(dof_id) !=
+common/time_step_solvers/time_step_solver_default.cc: this->integration_schemes.end()) {
+common/time_step_solvers/time_step_solver_default.cc: this->integration_schemes[dof_id] = std::move(integration_scheme);
+common/time_step_solvers/time_step_solver_default.cc: this->solution_types[dof_id] = solution_type;
+common/time_step_solvers/time_step_solver_default.cc: this->integration_schemes_owner.insert(dof_id);
+common/time_step_solvers/time_step_solver_default.cc: return this->integration_schemes.find(dof_id) !=
+common/time_step_solvers/time_step_solver_default.cc: this->integration_schemes.end();
+common/time_step_solvers/time_step_solver_default.cc: this->solver_callback = &solver_callback;
+common/time_step_solvers/time_step_solver_default.cc: this->non_linear_solver.solve(*this);
+common/time_step_solvers/time_step_solver_default.cc: this->solver_callback = nullptr;
+common/time_step_solvers/time_step_solver_default.cc: for (auto && [dof_id, integration_scheme] : this->integration_schemes) {
+common/time_step_solvers/time_step_solver_default.cc: if (this->_dof_manager.hasPreviousDOFs(dof_id)) {
+common/time_step_solvers/time_step_solver_default.cc: this->_dof_manager.savePreviousDOFs(dof_id);
+common/time_step_solvers/time_step_solver_default.cc: integration_scheme->predictor(this->time_step);
+common/time_step_solvers/time_step_solver_default.cc: for (auto && [dof_id, integration_scheme] : this->integration_schemes) {
+common/time_step_solvers/time_step_solver_default.cc: const auto & solution_type = this->solution_types[dof_id];
+common/time_step_solvers/time_step_solver_default.cc: integration_scheme->corrector(solution_type, this->time_step);
+common/time_step_solvers/time_step_solver_default.cc: if (this->_dof_manager.hasDOFsIncrement(dof_id)) {
+common/time_step_solvers/time_step_solver_default.cc: if (not this->_dof_manager.hasPreviousDOFs(dof_id)) {
+common/time_step_solvers/time_step_solver_default.cc: auto & increment = this->_dof_manager.getDOFsIncrement(dof_id);
+common/time_step_solvers/time_step_solver_default.cc: auto & previous = this->_dof_manager.getPreviousDOFs(dof_id);
+common/time_step_solvers/time_step_solver_default.cc: auto dof_array_comp = this->_dof_manager.getDOFs(dof_id).getNbComponent();
+common/time_step_solvers/time_step_solver_default.cc: increment.copy(this->_dof_manager.getSolution(dof_id), true);
+common/time_step_solvers/time_step_solver_default.cc: increment.copy(this->_dof_manager.getDOFs(dof_id));
+common/time_step_solvers/time_step_solver_default.cc: const auto & solution_type = this->solution_types[dof_id];
+common/time_step_solvers/time_step_solver_default.cc: integration_scheme.assembleJacobian(solution_type, this->time_step);
+common/time_step_solvers/time_step_solver_default.cc: this->_dof_manager.applyBoundary("J");
+common/time_step_solvers/time_step_solver_default.cc: if (this->needed_matrices.find("M") != needed_matrices.end()) {
+common/time_step_solvers/time_step_solver_default.cc: if (this->is_mass_lumped) {
+common/time_step_solvers/time_step_solver_default.cc: this->assembleLumpedMatrix("M");
+common/time_step_solvers/time_step_solver_default.cc: this->assembleMatrix("M");
+common/time_step_solvers/time_step_solver_default.cc: integration_scheme.assembleResidual(this->is_mass_lumped);
+common/time_step_solvers/time_step_solver_default.cc: if (this->needed_matrices.find("M") != needed_matrices.end()) {
+common/time_step_solvers/time_step_solver_default.cc: if (this->is_mass_lumped) {
+common/time_step_solvers/time_step_solver_default.cc: this->assembleLumpedMatrix("M");
+common/time_step_solvers/time_step_solver_default.cc: this->assembleMatrix("M");
+common/time_step_solvers/time_step_solver_default.cc: integration_scheme.assembleResidual(this->is_mass_lumped);
+common/time_step_solvers/time_step_solver_default.hh: for (auto && [dof_id, integration_scheme] : this->integration_schemes) {
+common/time_step_solvers/time_step_solver.cc: this->registerSubRegistry("non_linear_solver", non_linear_solver);
+common/time_step_solvers/time_step_solver.cc: auto scheme = this->getIntegrationSchemeInternal(dof_id, type, solution_type);
+common/time_step_solvers/time_step_solver.cc: this->setIntegrationScheme(dof_id, scheme, solution_type);
+common/time_step_solvers/time_step_solver.cc: this->setIntegrationSchemeInternal(dof_id, scheme, solution_type);
+common/time_step_solvers/time_step_solver.cc: mat_type = this->solver_callback->getMatrixType(name);
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->predictor();
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->corrector();
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->beforeSolveStep();
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->afterSolveStep(converged);
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->assembleLumpedMatrix(matrix_id);
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: auto common_type = this->getCommonMatrixType();
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->assembleMatrix(matrix_id);
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->assembleMatrix(name);
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->_dof_manager.zeroResidual();
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->assembleResidual();
+common/time_step_solvers/time_step_solver.cc: this->solver_callback != nullptr,
+common/time_step_solvers/time_step_solver.cc: this->solver_callback->assembleResidual(residual_part);
+common/integration_scheme/newmark-beta.cc: this->registerParam("alpha", this->alpha, alpha, _pat_parsmod,
+common/integration_scheme/newmark-beta.cc: this->registerParam("beta", this->beta, beta, _pat_parsmod,
+common/integration_scheme/newmark-beta.cc: this->allCorrector<_acceleration>(delta_t, u, u_dot, u_dot_dot,
+common/integration_scheme/newmark-beta.cc: this->allCorrector<_velocity>(delta_t, u, u_dot, u_dot_dot, blocked_dofs,
+common/integration_scheme/newmark-beta.cc: this->allCorrector<_displacement>(delta_t, u, u_dot, u_dot_dot,
+common/integration_scheme/newmark-beta.cc: auto & J = this->dof_manager.getMatrix("J");
+common/integration_scheme/newmark-beta.cc: const auto & M = this->dof_manager.getMatrix("M");
+common/integration_scheme/newmark-beta.cc: auto c = this->getAccelerationCoefficient(type, delta_t);
+common/integration_scheme/newmark-beta.cc: auto e = this->getDisplacementCoefficient(type, delta_t);
+common/integration_scheme/newmark-beta.cc: const auto & K = this->dof_manager.getMatrix("K");
+common/integration_scheme/newmark-beta.cc: if (this->dof_manager.hasMatrix("C")) {
+common/integration_scheme/newmark-beta.cc: const auto & C = this->dof_manager.getMatrix("C");
+common/integration_scheme/newmark-beta.cc: does_j_need_update |= this->dof_manager.hasBlockedDOFsChanged();
+common/integration_scheme/newmark-beta.cc: const auto & K = this->dof_manager.getMatrix("K");
+common/integration_scheme/newmark-beta.cc: if (this->dof_manager.hasMatrix("C")) {
+common/integration_scheme/newmark-beta.cc: auto d = this->getVelocityCoefficient(type, delta_t);
+common/integration_scheme/newmark-beta.cc: const auto & C = this->dof_manager.getMatrix("C");
+common/integration_scheme/integration_scheme_1st_order.cc: Array<Real> & u = this->dof_manager.getDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_1st_order.cc: Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1);
+common/integration_scheme/integration_scheme_1st_order.cc: this->dof_manager.getBlockedDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_1st_order.cc: this->predictor(delta_t, u, u_dot, blocked_dofs);
+common/integration_scheme/integration_scheme_1st_order.cc: Array<Real> & u = this->dof_manager.getDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_1st_order.cc: Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1);
+common/integration_scheme/integration_scheme_1st_order.cc: const Array<Real> & solution = this->dof_manager.getSolution(this->dof_id);
+common/integration_scheme/integration_scheme_1st_order.cc: this->dof_manager.getBlockedDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_1st_order.cc: this->corrector(type, delta_t, u, u_dot, blocked_dofs, solution);
+common/integration_scheme/integration_scheme_1st_order.cc: dof_manager.getDOFsDerivatives(this->dof_id, 1);
+common/integration_scheme/integration_scheme_1st_order.cc: if (this->dof_manager.hasMatrix("M")) {
+common/integration_scheme/integration_scheme_1st_order.cc: this->dof_manager.assembleMatMulVectToResidual(this->dof_id, "M",
+common/integration_scheme/integration_scheme_1st_order.cc: if (this->dof_manager.hasLumpedMatrix("M")) {
+common/integration_scheme/integration_scheme_1st_order.cc: this->dof_manager.assembleLumpedMatMulVectToResidual(
+common/integration_scheme/integration_scheme_1st_order.cc: this->dof_id, "M", first_derivative, -1);
+common/integration_scheme/integration_scheme_2nd_order.cc: Array<Real> & u = this->dof_manager.getDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_2nd_order.cc: Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.getDOFsDerivatives(this->dof_id, 2);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.getBlockedDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->predictor(delta_t, u, u_dot, u_dot_dot, blocked_dofs);
+common/integration_scheme/integration_scheme_2nd_order.cc: Array<Real> & u = this->dof_manager.getDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_2nd_order.cc: Array<Real> & u_dot = this->dof_manager.getDOFsDerivatives(this->dof_id, 1);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.getDOFsDerivatives(this->dof_id, 2);
+common/integration_scheme/integration_scheme_2nd_order.cc: const Array<Real> & solution = this->dof_manager.getSolution(this->dof_id);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.getBlockedDOFs(this->dof_id);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->corrector(type, delta_t, u, u_dot, u_dot_dot, blocked_dofs, solution);
+common/integration_scheme/integration_scheme_2nd_order.cc: if (this->dof_manager.hasMatrix("C")) {
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.getDOFsDerivatives(this->dof_id, 1);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.assembleMatMulVectToResidual(this->dof_id, "C",
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.getDOFsDerivatives(this->dof_id, 2);
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.assembleMatMulVectToResidual(this->dof_id, "M",
+common/integration_scheme/integration_scheme_2nd_order.cc: this->dof_manager.assembleLumpedMatMulVectToResidual(this->dof_id, "M",
+model.cc: this->mesh.registerEventHandler(*this, _ehp_model);
+model.cc: if (!this->hasDefaultSolver()) {
+model.cc: this->initNewSolver(this->method);
+model.cc: std::tie(solver_name, tss_type) = this->getDefaultSolverID(method);
+model.cc: if (not this->hasSolver(solver_name)) {
+model.cc: ModelSolverOptions options = this->getDefaultSolverOptions(tss_type);
+model.cc: this->getNewSolver(solver_name, tss_type, options.non_linear_solver_type);
+model.cc: if (!this->hasIntegrationScheme(solver_name, is_type.first)) {
+model.cc: this->setIntegrationScheme(solver_name, is_type.first, is_type.second,
+model.cc: this->method = method;
+model.cc: this->setDefaultSolver(solver_name);
+model.cc: this->addDumpFieldToDumper(mesh.getDefaultDumperName(), field_id);
+model.cc: this->addDumpFieldVectorToDumper(mesh.getDefaultDumperName(), field_id);
+model.cc: this->addDumpFieldTensorToDumper(mesh.getDefaultDumperName(), field_id);
+model.cc: this->addDumpGroupFieldToDumper(dumper_name, field_id, "all",
+model.cc: this->addDumpGroupFieldToDumper(group.getDefaultDumperName(), field_id,
+model.cc: this->removeDumpGroupFieldFromDumper(group.getDefaultDumperName(), field_id,
+model.cc: this->addDumpGroupFieldToDumper(dumper_name, field_id, "all",
+model.cc: this->addDumpGroupFieldVectorToDumper(group.getDefaultDumperName(), field_id,
+model.cc: this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name,
+model.cc: this->addDumpGroupFieldToDumper(dumper_name, field_id, "all",
+model.cc: this->addDumpGroupFieldToDumper(dumper_name, field_id, group_name,
+model.cc: this->spatial_dimension, element_kind,
+model.cc: field = this->createNodalFieldReal(field_id, group_name, padding_flag);
+model.cc: field = this->createNodalFieldInt(field_id, group_name, padding_flag);
+model.cc: field = this->createNodalFieldBool(field_id, group_name, padding_flag);
+model.cc: field = this->createElementalField(field_id, group_name, padding_flag,
+model.cc: field = this->mesh.createFieldFromAttachedData<Int>(field_id, group_name,
+model.cc: field = this->mesh.createFieldFromAttachedData<Real>(field_id, group_name,
+model.cc: this->addDumpGroupFieldToDumper(field_id, field, dumper);
+model.cc: this->dump(default_dumper);
+model.cc: this->dump(default_dumper, step);
+model.cc: this->dump(default_dumper, time, step);
+structural_mechanics/structural_mechanics_model.cc: this->mesh.registerDumper<DumperParaview>("structural_mechanics_model", id,
+structural_mechanics/structural_mechanics_model.cc: this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_structural);
+structural_mechanics/structural_mechanics_model.cc: this->initDOFManager();
+structural_mechanics/structural_mechanics_model.cc: this->dumper_default_element_kind = _ek_structural;
+structural_mechanics/structural_mechanics_model.cc: this->mesh.getDumper().setTimeStep(time_step);
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(displacement_rotation, nb_degree_of_freedom,
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(external_force, nb_degree_of_freedom, "external_force");
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(internal_force, nb_degree_of_freedom, "internal_force");
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(blocked_dofs, nb_degree_of_freedom, "blocked_dofs");
+structural_mechanics/structural_mechanics_model.cc: auto & dof_manager = this->getDOFManager();
+structural_mechanics/structural_mechanics_model.cc: dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs);
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(velocity, nb_degree_of_freedom, "velocity");
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(acceleration, nb_degree_of_freedom, "acceleration");
+structural_mechanics/structural_mechanics_model.cc: dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity);
+structural_mechanics/structural_mechanics_model.cc: *this->acceleration);
+structural_mechanics/structural_mechanics_model.cc: this->allocateLumpedMassArray();
+structural_mechanics/structural_mechanics_model.cc: this->getDOFManager().zeroMatrix("K");
+structural_mechanics/structural_mechanics_model.cc: this->assembleStiffnessMatrix<type>();
+structural_mechanics/structural_mechanics_model.cc: this->computeStressOnQuad<type>();
+structural_mechanics/structural_mechanics_model.cc: this->allocNodalField(this->mass, this->nb_degree_of_freedom, "lumped_mass");
+structural_mechanics/structural_mechanics_model.cc: AKANTU_DEBUG_ASSERT(this->mass.get() != nullptr,
+structural_mechanics/structural_mechanics_model.cc: return mesh.createStridedNodalField(this->mass.get(), group_name, n, 0,
+structural_mechanics/structural_mechanics_model.cc: ElementTypeMap<Int> nb_data_per_elem = this->mesh.getNbDataPerElem(stress);
+structural_mechanics/structural_mechanics_model.cc: stress, group_name, this->spatial_dimension, kind, nb_data_per_elem);
+structural_mechanics/structural_mechanics_model.cc: this->assembleLumpedMassMatrix();
+structural_mechanics/structural_mechanics_model.cc: auto & dof_manager = this->getDOFManager();
+structural_mechanics/structural_mechanics_model.cc: dof_manager.assembleToResidual("displacement", *this->external_force, 1);
+structural_mechanics/structural_mechanics_model.cc: this->assembleInternalForce();
+structural_mechanics/structural_mechanics_model.cc: dof_manager.assembleToResidual("displacement", *this->internal_force, 1);
+structural_mechanics/structural_mechanics_model.cc: if (this->method == _explicit_consistent_mass) {
+structural_mechanics/structural_mechanics_model.cc: const UInt nb_degree_of_freedom = this->nb_degree_of_freedom;
+structural_mechanics/structural_mechanics_model.cc: if (this->getDOFManager().hasLumpedMatrix("M")) {
+structural_mechanics/structural_mechanics_model.cc: AKANTU_DEBUG_ASSERT(this->mass != nullptr,
+structural_mechanics/structural_mechanics_model.cc: this->assembleLumpedMatrix("M");
+structural_mechanics/structural_mechanics_model.cc: zip(arange(nb_nodes), make_view(*this->velocity, nb_degree_of_freedom),
+structural_mechanics/structural_mechanics_model.cc: make_view(*this->mass, nb_degree_of_freedom))) {
+structural_mechanics/structural_mechanics_model.cc: } else if (this->getDOFManager().hasMatrix("M")) {
+structural_mechanics/structural_mechanics_model.cc: this->assembleMassMatrix();
+structural_mechanics/structural_mechanics_model.cc: this->getDOFManager().assembleMatMulVectToArray("displacement", "M",
+structural_mechanics/structural_mechanics_model.cc: *this->velocity, Mv);
+structural_mechanics/structural_mechanics_model.cc: make_view(*this->velocity, nb_degree_of_freedom))) {
+structural_mechanics/structural_mechanics_model.cc: this->assembleStiffnessMatrix();
+structural_mechanics/structural_mechanics_model.cc: this->getDOFManager().assembleMatMulVectToArray(
+structural_mechanics/structural_mechanics_model.cc: "displacement", "K", *this->displacement_rotation, Ku);
+structural_mechanics/structural_mechanics_model.cc: make_view(*this->displacement_rotation, nb_degree_of_freedom))) {
+model_couplers/coupler_solid_cohesive_contact.cc: this->initDOFManager(dof_manager);
+model_couplers/coupler_solid_cohesive_contact.cc: this->mesh.registerDumper<DumperParaview>("coupler_solid_cohesive_contact",
+model_couplers/coupler_solid_cohesive_contact.cc: this->mesh.addDumpMeshToDumper("coupler_solid_cohesive_contact", mesh,
+model_couplers/coupler_solid_cohesive_contact.cc: this->registerDataAccessor(*this);
+model_couplers/coupler_solid_cohesive_contact.cc: this->dof_manager);
+phase_field/phase_field_model.hh: this->setConstitutiveLawSelector(selector);
+phase_field/phasefield.cc: g_c(this->registerInternal<Real, DefaultRandomInternalField>(
+phase_field/phasefield.cc: damage_on_qpoints(this->registerInternal("damage", 1, fe_engine_id)),
+phase_field/phasefield.cc: gradd(this->registerInternal("grad_d", spatial_dimension, fe_engine_id)),
+phase_field/phasefield.cc: phi(this->registerInternal("phi", 1, fe_engine_id)),
+phase_field/phasefield.cc: strain(this->registerInternal(
+phase_field/phasefield.cc: driving_force(this->registerInternal("driving_force", 1, fe_engine_id)),
+phase_field/phasefield.cc: driving_energy(this->registerInternal("driving_energy", spatial_dimension,
+phase_field/phasefield.cc: damage_energy(this->registerInternal(
+phase_field/phasefield.cc: this->registerInternal("damage_energy_density", 1, fe_engine_id)),
+phase_field/phasefield.cc: this->registerInternal("dissipated_energy", 1, fe_engine_id)) {
+phase_field/phasefield.cc: this->phi.initializeHistory();
+phase_field/phasefield.cc: this->damage_on_qpoints.initializeHistory();
+phase_field/phasefield.cc: this->registerParam("l0", l0, Real(0.), _pat_parsable | _pat_readable,
+phase_field/phasefield.cc: this->registerParam("gc", g_c, _pat_parsable | _pat_readable,
+phase_field/phasefield.cc: this->registerParam("E", E, _pat_parsable | _pat_readable, "Young's modulus");
+phase_field/phasefield.cc: this->registerParam("nu", nu, _pat_parsable | _pat_readable, "Poisson ratio");
+phase_field/phasefield.cc: this->registerParam("isotropic", isotropic, true,
+phase_field/phasefield.cc: this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
+phase_field/phasefield.cc: if (this->plane_stress) {
+phase_field/phasefield.cc: this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu));
+phase_field/phasefield.cc: this->mu = this->E / (2 * (1 + this->nu));
+phase_field/phasefield.cc: auto & fem = this->getFEEngine();
+phase_field/phasefield.cc: for (const auto & type : this->getElementFilter().elementTypes(
+phase_field/phasefield.cc: this->spatial_dimension, ghost_type)) {
+phase_field/phasefield.cc: auto & elem_filter = this->getElementFilter(type, ghost_type);
+phase_field/phasefield.cc: auto & fem = this->getFEEngine();
+phase_field/phasefield.cc: auto & fem = this->getFEEngine();
+phase_field/phasefield.cc: auto & fem = this->getFEEngine();
+phase_field/phasefield.cc: auto & fem = this->getFEEngine();
+phase_field/phasefield.cc: auto & fem = this->getFEEngine();
+phase_field/phasefield.cc: // this->savePreviousState();
+phase_field/phasefield.cc: this->computeAllDrivingForces(_not_ghost);
+model_couplers/coupler_solid_phasefield.cc: this->registerFEEngineObject<MyFEEngineType>("CouplerSolidPhaseField", mesh,
+model_couplers/coupler_solid_phasefield.cc: this->mesh.registerDumper<DumperParaview>("coupler_solid_phasefield", id,
+model_couplers/coupler_solid_phasefield.cc: this->mesh.addDumpMeshToDumper("coupler_solid_phasefield", mesh,
+model_couplers/coupler_solid_phasefield.cc: this->registerDataAccessor(*this);
+model_couplers/coupler_solid_phasefield.cc: if (this->mesh.isDistributed()) {
+model_couplers/coupler_solid_phasefield.cc: auto & synchronizer = this->mesh.getElementSynchronizer();
+model_couplers/coupler_solid_phasefield.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_csp_damage);
+model_couplers/coupler_solid_phasefield.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_csp_strain);
+model_couplers/coupler_solid_phasefield.cc: this->initBC(*this, *displacement, *displacement_increment, *external_force);
+model_couplers/coupler_solid_phasefield.cc: solid->initFull(_analysis_method = this->method);
+model_couplers/coupler_solid_phasefield.cc: phase->initFull(_analysis_method = this->method);
+model_couplers/coupler_solid_phasefield.cc: this->assembleInternalForces();
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("displacement", solid_external_force,
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("displacement", solid_internal_force,
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("damage", phasefield_external_force,
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("damage", phasefield_internal_force,
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("displacement",
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("displacement",
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("damage",
+model_couplers/coupler_solid_phasefield.cc: this->getDOFManager().assembleToResidual("damage",
+model_couplers/coupler_solid_phasefield.cc: this->assembleStiffnessMatrix();
+model_couplers/coupler_solid_phasefield.cc: mesh.elementTypes(this->spatial_dimension, ghost_type)) {
+model_couplers/coupler_solid_phasefield.cc: this->spatial_dimension);
+model_couplers/coupler_solid_phasefield.cc: this->computeStrainOnQuadPoints(_not_ghost);
+model_couplers/coupler_solid_phasefield.cc: this->computeStrainOnQuadPoints(_ghost);
+model_couplers/coupler_solid_phasefield.cc: this->computeDamageOnQuadPoints(_not_ghost);
+model_couplers/coupler_solid_phasefield.cc: this->computeDamageOnQuadPoints(_ghost);
+model_couplers/coupler_solid_contact.cc: this->initDOFManager(dof_manager);
+model_couplers/coupler_solid_contact.cc: this->mesh.registerDumper<DumperParaview>("coupler_solid_contact", id, true);
+model_couplers/coupler_solid_contact.cc: this->mesh.addDumpMeshToDumper("coupler_solid_contact", mesh,
+model_couplers/coupler_solid_contact.cc: this->registerDataAccessor(*this);
+model_couplers/coupler_solid_contact.cc: this->dof_manager);
+model_couplers/coupler_solid_contact.cc: this->dof_manager);
+model_couplers/coupler_solid_contact.cc: solid->initFull(_analysis_method = this->method);
+model_couplers/coupler_solid_contact.cc: contact->initFull(_analysis_method = this->method);
+phase_field/phasefield.hh: void initConstitutiveLaw() override { this->initPhaseField(); }
+model_couplers/coupler_solid_contact_tmpl.hh: this->assembleInternalForces();
+model_couplers/coupler_solid_contact_tmpl.hh: this->getDOFManager().assembleToResidual("displacement", external_force, 1);
+model_couplers/coupler_solid_contact_tmpl.hh: this->getDOFManager().assembleToResidual("displacement", internal_force, 1);
+model_couplers/coupler_solid_contact_tmpl.hh: this->getDOFManager().assembleToResidual("displacement", contact_force, 1);
+model_couplers/coupler_solid_contact_tmpl.hh: this->getDOFManager().assembleToResidual("displacement", external_force, 1);
+model_couplers/coupler_solid_contact_tmpl.hh: this->getDOFManager().assembleToResidual("displacement", contact_force, 1);
+model_couplers/coupler_solid_contact_tmpl.hh: this->getDOFManager().assembleToResidual("displacement", internal_force, 1);
+model_couplers/coupler_solid_contact_tmpl.hh: this->assembleStiffnessMatrix();
+structural_mechanics/structural_mechanics_model.hh: if (this->mass == nullptr) {
+structural_mechanics/structural_mechanics_model.hh: return *(this->mass);
+structural_mechanics/structural_mechanics_model.hh: inline const Array<Real> & getMass() const { return this->getLumpedMass(); }
+structural_mechanics/structural_mechanics_model.hh: inline bool hasLumpedMass() const { return (this->mass != nullptr); };
+phase_field/phase_field_model.cc: this->initDOFManager(std::move(dof_manager));
+phase_field/phase_field_model.cc: this->registerFEEngineObject<FEEngineType>("PhaseFieldFEEngine", mesh,
+phase_field/phase_field_model.cc: this->mesh.registerDumper<DumperParaview>("phase_field", id, true);
+phase_field/phase_field_model.cc: this->mesh.addDumpMesh(mesh, Model::spatial_dimension, _not_ghost,
+phase_field/phase_field_model.cc: if (this->mesh.isDistributed()) {
+phase_field/phase_field_model.cc: auto & synchronizer = this->mesh.getElementSynchronizer();
+phase_field/phase_field_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_pfm_damage);
+phase_field/phase_field_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_for_dump);
+phase_field/phase_field_model.cc: this->parser_type = ParserType::_phasefield;
+phase_field/phase_field_model.cc: this->initBC(*this, *damage, *external_force);
+phase_field/phase_field_model.cc: this->assembleStiffnessMatrix();
+phase_field/phase_field_model.cc: DOFManager & dof_manager = this->getDOFManager();
+phase_field/phase_field_model.cc: this->allocNodalField(this->damage, 1, "damage");
+phase_field/phase_field_model.cc: this->allocNodalField(this->external_force, 1, "external_force");
+phase_field/phase_field_model.cc: this->allocNodalField(this->internal_force, 1, "internal_force");
+phase_field/phase_field_model.cc: this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
+phase_field/phase_field_model.cc: this->allocNodalField(this->previous_damage, 1, "previous_damage");
+phase_field/phase_field_model.cc: dof_manager.registerDOFs("damage", *this->damage, _dst_nodal);
+phase_field/phase_field_model.cc: dof_manager.registerBlockedDOFs("damage", *this->blocked_dofs);
+phase_field/phase_field_model.cc: dof_manager.registerDOFsPrevious("damage", *this->previous_damage);
+phase_field/phase_field_model.cc: auto phase_index = this->getConstitutiveLawByElement()(element);
+phase_field/phase_field_model.cc: pf_element.element = this->getConstitutiveLawLocalNumbering()(element);
+phase_field/phase_field_model.cc: this->getConstitutiveLaw(phase_index).getEnergy(energy_id, pf_element);
+phase_field/phase_field_model.cc: energy += this->getEnergy(energy_id, el);
+phase_field/phase_field_model.cc: if (!this->getDOFManager().hasMatrix("K")) {
+phase_field/phase_field_model.cc: this->getDOFManager().getNewMatrix("K", getMatrixType("K"));
+phase_field/phase_field_model.cc: this->getDOFManager().zeroMatrix("K");
+phase_field/phase_field_model.cc: this->assembleInternalForces();
+phase_field/phase_field_model.cc: this->getDOFManager().assembleToResidual("damage", *this->external_force, 1);
+phase_field/phase_field_model.cc: this->getDOFManager().assembleToResidual("damage", *this->internal_force, 1);
+phase_field/phase_field_model.cc: this->internal_force->zero();
+phase_field/phase_field_model.cc: this->synchronize(SynchronizationTag::_pfm_damage);
+phase_field/phase_field_model.cc: this->mesh.getDumper("phase_field").setTimeStep(time_step);
+phase_field/phase_field_model.cc: mesh.getConnectivities(), group_name, this->spatial_dimension,
+structural_mechanics/structural_mechanics_model_mass.cc: this->getDOFManager().zeroMatrix("M");
+structural_mechanics/structural_mechanics_model_mass.cc: this->getDOFManager(), type, ghost_type);
+structural_mechanics/structural_mechanics_model_mass.cc: if (not this->need_to_reassemble_lumped_mass) {
+structural_mechanics/structural_mechanics_model_mass.cc: allocNodalField(this->mass, nb_degree_of_freedom, "lumped_mass");
+structural_mechanics/structural_mechanics_model_mass.cc: if (!this->getDOFManager().hasLumpedMatrix("M")) {
+structural_mechanics/structural_mechanics_model_mass.cc: this->getDOFManager().getNewLumpedMatrix("M");
+structural_mechanics/structural_mechanics_model_mass.cc: this->getDOFManager().zeroLumpedMatrix("M");
+structural_mechanics/structural_mechanics_model_mass.cc: auto & lumped_mass = *(this->mass);
+structural_mechanics/structural_mechanics_model_mass.cc: const auto & element_material_id = this->element_material(type);
+structural_mechanics/structural_mechanics_model_mass.cc: const auto & material = this->materials.at(std::get<1>(data));
+structural_mechanics/structural_mechanics_model_mass.cc: this->getDOFManager().assembleToLumpedMatrix("displacement", lumped_mass,
+structural_mechanics/structural_mechanics_model_mass.cc: this->need_to_reassemble_lumped_mass = false;
+model.hh: switch (this->model_type) {
+model.hh: this->initFullImpl(SolidMechanicsModelOptions{
+model.hh: this->initFullImpl(SolidMechanicsModelCohesiveOptions{
+model.hh: this->initFullImpl(HeatTransferModelOptions{
+model.hh: this->initFullImpl(PhaseFieldModelOptions{
+model.hh: this->initFullImpl(EmbeddedInterfaceModelOptions{
+model.hh: this->initFullImpl(ContactMechanicsModelOptions{
+model.hh: this->initFullImpl(CouplerSolidContactOptions{
+model.hh: this->initFullImpl(CouplerSolidCohesiveContactOptions{
+model.hh: this->initFullImpl(ModelOptions{use_named_args,
+model.hh: this->initFullImpl(std::forward<decltype(_pack)>(_pack)...);
+phase_field/phasefields/phasefield_linear_inline_impl.hh: edis += 3. / 8 * g_c_quad * this->l0 * grad_d[i] * grad_d[i];
+phase_field/phasefields/phasefield_linear_inline_impl.hh: edis += 3 * g_c_quad * dam * dam / (8 * this->l0);
+phase_field/phasefields/phasefield_linear_inline_impl.hh: edis += 0.5 * this->gamma * damage_penalized * damage_penalized;
+phase_field/phasefields/phasefield_linear_inline_impl.hh: driving_force_quad = phi_quad - 3 * g_c_quad / (16 * this->l0);
+phase_field/phasefields/phasefield_linear_inline_impl.hh: Real kpa = this->lambda + 2. * this->mu / Real(dev_dim);
+phase_field/phasefields/phasefield_linear_inline_impl.hh: this->mu * strain_dev.doubleDot(strain_dev);
+phase_field/phasefields/phasefield_linear_inline_impl.hh: phi_quad = 0.5 * this->lambda * trace * trace +
+phase_field/phasefields/phasefield_linear_inline_impl.hh: this->mu * strain_quad.doubleDot(strain_quad);
+diffusion_model/diffusion_law.cc: this->getFEEngine().gradientOnIntegrationPoints(
+diffusion_model/diffusion_law.cc: this->computeGradU(type, ghost_type);
+diffusion_model/diffusion_law.cc: this->computeDiffusivityGradUOnQuadPoints(type, ghost_type);
+diffusion_model/diffusion_law.cc: auto && model = this->getHandler();
+diffusion_model/diffusion_law.cc: auto & fem = this->getFEEngine();
+diffusion_model/diffusion_law.cc: auto & model = this->getHandler();
+diffusion_model/diffusion_law.cc: packElementalDataHelper(this->grad_u, buffer, elements,
+diffusion_model/diffusion_law.cc: this->getFEEngine());
+solid_mechanics/solid_mechanics_model_mass.cc: this->allocNodalField(this->mass, spatial_dimension, "mass");
+solid_mechanics/solid_mechanics_model_mass.cc: if (!this->getDOFManager().hasLumpedMatrix("M")) {
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager().getNewLumpedMatrix("M");
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager().zeroLumpedMatrix("M");
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager().getLumpedMatrixPerDOFs("displacement", "M",
+solid_mechanics/solid_mechanics_model_mass.cc: *(this->mass));
+solid_mechanics/solid_mechanics_model_mass.cc: this->synchronize(SynchronizationTag::_smm_mass);
+solid_mechanics/solid_mechanics_model_mass.cc: if (not this->getDOFManager().hasMatrix("M")) {
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager().getNewMatrix("M", this->getMatrixType("M"));
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager().zeroMatrix("M");
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager(), type, ghost_type);
+solid_mechanics/solid_mechanics_model_mass.cc: this->getDOFManager(), type, ghost_type);
+common/non_linear_solver/non_linear_solver_petsc.cc: this->has_internal_set_param = true;
+common/non_linear_solver/non_linear_solver_petsc.cc: this->checkIfTypeIsSupported();
+common/non_linear_solver/non_linear_solver_petsc.cc: void setCallback(SolverCallback & callback) { this->callback = &callback; }
+common/non_linear_solver/non_linear_solver_petsc.cc: _this->assembleResidual(x);
+common/non_linear_solver/non_linear_solver_petsc.cc: _this->assembleJacobian(x);
+common/non_linear_solver/non_linear_solver_petsc.cc: this->dof_manager.updateGlobalBlockedDofs();
+common/non_linear_solver/non_linear_solver_petsc.cc: this->reason, this->n_iter, stol, atol, rtol, maxit));
+solid_mechanics/material.hh: void initConstitutiveLaw() override { this->initMaterial(); }
+solid_mechanics/material.hh: return this->getHandler();
+solid_mechanics/material.hh: [[nodiscard]] SolidMechanicsModel & getModel() { return this->getHandler(); }
+solid_mechanics/material.hh: make_view(this->gradu(el_type, ghost_type), this->spatial_dimension, \
+solid_mechanics/material.hh: this->spatial_dimension); \
+solid_mechanics/material.hh: make_view(this->stress(el_type, ghost_type), this->spatial_dimension, \
+solid_mechanics/material.hh: this->spatial_dimension); \
+solid_mechanics/material.hh: if (this->isFiniteDeformation()) { \
+solid_mechanics/material.hh: stress_view = make_view((*this->piola_kirchhoff_2)(el_type, ghost_type), \
+solid_mechanics/material.hh: this->spatial_dimension, this->spatial_dimension); \
+solid_mechanics/material.hh: make_view(this->gradu(el_type, ghost_type), this->spatial_dimension, \
+solid_mechanics/material.hh: this->spatial_dimension); \
+solid_mechanics/material.hh: make_view(this->stress(el_type, ghost_type), this->spatial_dimension, \
+solid_mechanics/material.hh: this->spatial_dimension); \
+solid_mechanics/material.hh: Material::getTangentStiffnessVoigtSize(this->spatial_dimension); \
+solid_mechanics/solid_mechanics_model.hh: inline decltype(auto) getMaterials() { return this->getConstitutiveLaws(); }
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLaws();
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLaw(mat_index);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLaw(mat_index);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLaw(name);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLaw(name);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLaw(element);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLawIndex(name);
+solid_mechanics/solid_mechanics_model.hh: return this->getNbConstitutiveLaws();
+solid_mechanics/solid_mechanics_model.hh: void reassignMaterial() { this->reassignConstitutiveLaw(); }
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLawByElement();
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLawLocalNumbering();
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLawByElement(type, ghost_type);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLawLocalNumbering(type, ghost_type);
+solid_mechanics/solid_mechanics_model.hh: return this->getConstitutiveLawSelector();
+solid_mechanics/solid_mechanics_model.hh: this->setConstitutiveLawSelector(material_selector);
+solid_mechanics/material.cc: this->getModel().registerEventHandler(*this);
+solid_mechanics/material.cc: this->registerInternal("piola_kirchhoff_2",
+solid_mechanics/material.cc: this->piola_kirchhoff_2 = this->getSharedPtrInternal("piola_kirchhoff_2");
+solid_mechanics/material.cc: this->piola_kirchhoff_2->initializeHistory();
+solid_mechanics/material.cc: this->registerInternal("green_strain",
+solid_mechanics/material.cc: this->green_strain = this->getSharedPtrInternal("green_strain");
+solid_mechanics/material.cc: this->stress.initializeHistory();
+solid_mechanics/material.cc: this->gradu.initializeHistory();
+solid_mechanics/material.cc: this->assembleInternalForces<dim>(type, ghost_type);
+solid_mechanics/material.cc: this->assembleInternalForcesFiniteDeformation<dim>(type,
+solid_mechanics/material.cc: this->StoCauchy<dim>(type, ghost_type);
+solid_mechanics/material.cc: zip(make_view<dim, dim>(this->gradu(el_type, ghost_type)),
+solid_mechanics/material.cc: make_view<dim, dim>((*this->piola_kirchhoff_2)(el_type, ghost_type)),
+solid_mechanics/material.cc: make_view<dim, dim>(this->stress(el_type, ghost_type)))) {
+solid_mechanics/material.cc: this->StoCauchy<dim>(F, piola, sigma);
+solid_mechanics/material.cc: this->assembleStiffnessMatrixFiniteDeformation<dim>(type,
+solid_mechanics/material.cc: this->assembleStiffnessMatrix<dim>(type, ghost_type);
+solid_mechanics/material.cc: this->assembleStiffnessMatrix<dim, type>(ghost_type);
+solid_mechanics/material.cc: this->assembleStiffnessMatrixNL<dim, type>(ghost_type);
+solid_mechanics/material.cc: this->assembleStiffnessMatrixL2<dim, type>(ghost_type);
+solid_mechanics/material.cc: this->assembleInternalForces<dim, type>(ghost_type);
+solid_mechanics/material.cc: auto && fem = this->getFEEngine();
+solid_mechanics/material.cc: this->assembleInternalForcesFiniteDeformation<dim, type>(ghost_type);
+solid_mechanics/material.cc: zip(make_view<dim, dim>(this->gradu(type, ghost_type)),
+solid_mechanics/material.cc: make_view<dim, dim>((*this->piola_kirchhoff_2)(type, ghost_type)),
+solid_mechanics/material.cc: interpolation_points_coordinates, this->interpolation_points_matrices,
+solid_mechanics/material.cc: this->interpolation_inverse_coordinates, &(this->getElementFilter()));
+solid_mechanics/material.cc: this->stress, this->interpolation_points_matrices,
+solid_mechanics/material.cc: this->interpolation_inverse_coordinates, result, ghost_type,
+solid_mechanics/material.cc: &(this->getElementFilter()));
+solid_mechanics/material.cc: auto stress_size = this->stress.getNbComponent();
+solid_mechanics/material.cc: const auto & mesh = this->getModel().getMesh();
+solid_mechanics/material.cc:void Material::beforeSolveStep() { this->savePreviousState(); }
+solid_mechanics/material.cc: this->restorePreviousState();
+solid_mechanics/material.cc: this->updateEnergies(type);
+solid_mechanics/material.cc:void Material::onDamageIteration() { this->savePreviousState(); }
+solid_mechanics/material.cc: this->updateEnergiesAfterDamage(type);
+solid_mechanics/material.cc: if (this->isFiniteDeformation()) {
+solid_mechanics/material.cc: this->computeAllCauchyStresses(_not_ghost);
+solid_mechanics/material.cc: if (this->isInternal<Real>(id, element.kind())) {
+solid_mechanics/material.cc: auto name = this->getID() + ":" + id;
+solid_mechanics/material.cc: this->getInternal<Real>(name).getFEEngine().getNbIntegrationPoints(
+solid_mechanics/material.cc: this->getArray<Real>(id, element.type, element.ghost_type);
+solid_mechanics/material.cc: auto local_element = this->convertToLocalElement(element);
+solid_mechanics/material.cc: for (auto & eigengradu : make_view(this->eigengradu(type, ghost_type),
+solid_mechanics/solid_mechanics_model_io.cc: this->flattenAllRegisteredInternals(_ek_regular);
+solid_mechanics/solid_mechanics_model_io.cc: bool is_internal = this->isInternal(field_name_copy, kind);
+solid_mechanics/solid_mechanics_model_io.cc: this->getInternalDataPerElem(field_name_copy, kind);
+solid_mechanics/solid_mechanics_model_io.cc: auto & internal_flat = this->flattenInternal(field_name_copy, kind);
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["displacement"] = this->displacement.get();
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["mass"] = this->mass.get();
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["velocity"] = this->velocity.get();
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["acceleration"] = this->acceleration.get();
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["external_force"] = this->external_force.get();
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["internal_force"] = this->internal_force.get();
+solid_mechanics/solid_mechanics_model_io.cc: real_nodal_fields["increment"] = this->displacement_increment.get();
+solid_mechanics/solid_mechanics_model_io.cc: field = this->mesh.createNodalField(real_nodal_fields[field_name],
+solid_mechanics/solid_mechanics_model_io.cc: this->mesh.createNodalField(real_nodal_fields[field_name], group_name);
+solid_mechanics/solid_mechanics_model_io.cc: this->onDump();
+solid_mechanics/solid_mechanics_model_io.cc: this->onDump();
+solid_mechanics/solid_mechanics_model_io.cc: this->onDump();
+solid_mechanics/solid_mechanics_model_io.cc: this->onDump();
+solid_mechanics/solid_mechanics_model_io.cc: this->onDump();
+solid_mechanics/solid_mechanics_model_io.cc: this->onDump();
+diffusion_model/diffusion_model.cc: this->initDOFManager(dof_manager);
+diffusion_model/diffusion_model.cc: if (this->mesh.isDistributed()) {
+diffusion_model/diffusion_model.cc: auto & synchronizer = this->mesh.getElementSynchronizer();
+diffusion_model/diffusion_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_diffusion);
+diffusion_model/diffusion_model.cc: this->registerSynchronizer(synchronizer,
+diffusion_model/diffusion_model.cc: this->mesh.registerDumper<DumperParaview>(id, id, true);
+diffusion_model/diffusion_model.cc: this->mesh.addDumpMesh(mesh, spatial_dimension, _not_ghost, _ek_regular);
+diffusion_model/diffusion_model.cc: this->assembleDiffisivityMatrix();
+diffusion_model/diffusion_model.cc: this->assembleCapacityMatrix();
+diffusion_model/diffusion_model.cc: this->assembleCapacityMatrixLumped();
+diffusion_model/diffusion_model.cc: this->assembleInternalFlow();
+diffusion_model/diffusion_model.cc: this->getDOFManager().assembleToResidual(dof_name, *this->external_flow, 1);
+diffusion_model/diffusion_model.cc: this->getDOFManager().assembleToResidual(dof_name, *this->internal_flow, 1);
+diffusion_model/diffusion_model.cc: DOFManager & dof_manager = this->getDOFManager();
+diffusion_model/diffusion_model.cc: this->allocNodalField(this->diffusion, 1, dof_name);
+diffusion_model/diffusion_model.cc: this->allocNodalField(this->external_flow, 1, "external_flow");
+diffusion_model/diffusion_model.cc: this->allocNodalField(this->internal_flow, 1, "internal_flow");
+diffusion_model/diffusion_model.cc: this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
+diffusion_model/diffusion_model.cc: dof_manager.registerDOFs(dof_name, *this->diffusion, _dst_nodal);
+diffusion_model/diffusion_model.cc: dof_manager.registerBlockedDOFs(dof_name, *this->blocked_dofs);
+diffusion_model/diffusion_model.cc: this->allocNodalField(this->diffusion_rate, 1, dof_name + "_rate");
+diffusion_model/diffusion_model.cc: dof_manager.registerDOFsDerivative(dof_name, 1, *this->diffusion_rate);
+diffusion_model/diffusion_model.cc: if (this->method == _explicit_consistent_mass) {
+diffusion_model/diffusion_model.cc: AKANTU_DEBUG_ASSERT(this->getDOFManager().hasMatrix("K"),
+diffusion_model/diffusion_model.cc: this->getDOFManager().zeroMatrix("K");
+diffusion_model/diffusion_model.cc: this->internal_flow->zero();
+diffusion_model/diffusion_model.cc: this->synchronize(SynchronizationTag::_diffusion);
+diffusion_model/diffusion_model.cc: this->mesh.getDumper(id).setTimeStep(time_step);
+diffusion_model/diffusion_model.cc: if (!this->getDOFManager().hasLumpedMatrix("M")) {
+diffusion_model/diffusion_model.cc: this->getDOFManager().getNewLumpedMatrix("M");
+diffusion_model/diffusion_model.cc: this->getDOFManager().zeroLumpedMatrix("M");
+diffusion_model/diffusion_model.cc: fem.assembleFieldLumped(compute_rho, "M", dof_name, this->getDOFManager(),
+diffusion_model/diffusion_model.cc: this->getDOFManager().zeroMatrix("M");
+diffusion_model/diffusion_model.cc: fem.assembleFieldMatrix(rho_functor, "M", dof_name, this->getDOFManager(),
+diffusion_model/diffusion_model.cc: auto time_step = this->getTimeStep();
+diffusion_model/diffusion_model.cc: this->getConstitutiveLawLocalNumbering()(element);
+diffusion_model/diffusion_model.cc: return this->getConstitutiveLaw(element).getEnergy(energy_id,
+diffusion_model/diffusion_model.cc: mesh.getConnectivities(), group_name, this->spatial_dimension,
+diffusion_model/diffusion_model.cc: bool is_internal = this->isInternal(field_name, element_kind);
+diffusion_model/diffusion_model.cc: this->getInternalDataPerElem(field_name, element_kind);
+diffusion_model/diffusion_model.cc: auto & internal_flat = this->flattenInternal(field_name, element_kind);
+solid_mechanics/solid_mechanics_model.cc: this->initDOFManager(dof_manager);
+solid_mechanics/solid_mechanics_model.cc: this->registerFEEngineObject<MyFEEngineType>("SolidMechanicsFEEngine", mesh,
+solid_mechanics/solid_mechanics_model.cc: this->mesh.registerDumper<DumperParaview>("solid_mechanics_model", id, true);
+solid_mechanics/solid_mechanics_model.cc: this->mesh.addDumpMesh(mesh, Model::spatial_dimension, _not_ghost,
+solid_mechanics/solid_mechanics_model.cc: if (this->mesh.isDistributed()) {
+solid_mechanics/solid_mechanics_model.cc: auto & synchronizer = this->mesh.getElementSynchronizer();
+solid_mechanics/solid_mechanics_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_smm_mass);
+solid_mechanics/solid_mechanics_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_smm_stress);
+solid_mechanics/solid_mechanics_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_smm_gradu);
+solid_mechanics/solid_mechanics_model.cc: this->registerSynchronizer(synchronizer, SynchronizationTag::_for_dump);
+solid_mechanics/solid_mechanics_model.cc: this->parser_type = ParserType::_material;
+solid_mechanics/solid_mechanics_model.cc: this->mesh.getDumper().setTimeStep(time_step);
+solid_mechanics/solid_mechanics_model.cc: // if (not this->parser.getLastParsedFile().empty()) {
+solid_mechanics/solid_mechanics_model.cc: // this->instantiateMaterials();
+solid_mechanics/solid_mechanics_model.cc: // this->initConstitutiveLaws();
+solid_mechanics/solid_mechanics_model.cc: this->initBC(*this, *displacement, *displacement_increment, *external_force);
+solid_mechanics/solid_mechanics_model.cc: if (this->method == _explicit_consistent_mass) {
+solid_mechanics/solid_mechanics_model.cc: auto & dof_manager = this->getDOFManager();
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->displacement, spatial_dimension, "displacement");
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->previous_displacement, spatial_dimension,
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->displacement_increment, spatial_dimension,
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->internal_force, spatial_dimension,
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->external_force, spatial_dimension,
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->blocked_dofs, spatial_dimension, "blocked_dofs");
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->current_position, spatial_dimension,
+solid_mechanics/solid_mechanics_model.cc: this->current_position->copy(this->mesh.getNodes());
+solid_mechanics/solid_mechanics_model.cc: dof_manager.registerDOFs("displacement", *this->displacement, _dst_nodal);
+solid_mechanics/solid_mechanics_model.cc: dof_manager.registerBlockedDOFs("displacement", *this->blocked_dofs);
+solid_mechanics/solid_mechanics_model.cc: *this->displacement_increment);
+solid_mechanics/solid_mechanics_model.cc: *this->previous_displacement);
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->velocity, spatial_dimension, "velocity");
+solid_mechanics/solid_mechanics_model.cc: this->allocNodalField(this->acceleration, spatial_dimension,
+solid_mechanics/solid_mechanics_model.cc: dof_manager.registerDOFsDerivative("displacement", 1, *this->velocity);
+solid_mechanics/solid_mechanics_model.cc: *this->acceleration);
+solid_mechanics/solid_mechanics_model.cc: this->assembleInternalForces();
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().assembleToResidual("displacement",
+solid_mechanics/solid_mechanics_model.cc: *this->external_force, 1);
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().assembleToResidual("displacement",
+solid_mechanics/solid_mechanics_model.cc: *this->internal_force, 1);
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().assembleToResidual("displacement",
+solid_mechanics/solid_mechanics_model.cc: *this->external_force, 1);
+solid_mechanics/solid_mechanics_model.cc: this->assembleInternalForces();
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().assembleToResidual("displacement",
+solid_mechanics/solid_mechanics_model.cc: *this->internal_force, 1);
+solid_mechanics/solid_mechanics_model.cc: this->assembleStiffnessMatrix();
+solid_mechanics/solid_mechanics_model.cc: this->assembleMass();
+solid_mechanics/solid_mechanics_model.cc: this->assembleMassLumped();
+solid_mechanics/solid_mechanics_model.cc: this->internal_force->zero();
+solid_mechanics/solid_mechanics_model.cc: if (this->isNonLocal()) {
+solid_mechanics/solid_mechanics_model.cc: this->getNonLocalManager().computeAllNonLocalContribution();
+solid_mechanics/solid_mechanics_model.cc: this->asynchronousSynchronize(SynchronizationTag::_smm_stress);
+solid_mechanics/solid_mechanics_model.cc: this->waitEndSynchronize(SynchronizationTag::_smm_stress);
+solid_mechanics/solid_mechanics_model.cc: if (not this->getDOFManager().hasMatrix("K")) {
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().getNewMatrix("K", this->getMatrixType("K"));
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().getMatrix("K").zero();
+solid_mechanics/solid_mechanics_model.cc: if (this->current_position_release == this->displacement_release) {
+solid_mechanics/solid_mechanics_model.cc: this->current_position->copy(this->mesh.getNodes());
+solid_mechanics/solid_mechanics_model.cc: for (auto && data : zip(make_view(*this->current_position, spatial_dimension),
+solid_mechanics/solid_mechanics_model.cc: make_view(*this->displacement, spatial_dimension))) {
+solid_mechanics/solid_mechanics_model.cc: this->current_position_release = this->displacement_release;
+solid_mechanics/solid_mechanics_model.cc: this->updateCurrentPosition();
+solid_mechanics/solid_mechanics_model.cc: return *this->current_position;
+solid_mechanics/solid_mechanics_model.cc: this->updateCurrentPosition();
+solid_mechanics/solid_mechanics_model.cc: auto mat_indexes = this->getConstitutiveLawByElement(type, ghost_type);
+solid_mechanics/solid_mechanics_model.cc: auto mat_loc_num = this->getConstitutiveLawLocalNumbering(type, ghost_type);
+solid_mechanics/solid_mechanics_model.cc: auto el_c = this->getMaterial(mat_idx).getCelerity(elem);
+solid_mechanics/solid_mechanics_model.cc: if (this->getDOFManager().hasLumpedMatrix("M")) {
+solid_mechanics/solid_mechanics_model.cc: this->assembleLumpedMatrix("M");
+solid_mechanics/solid_mechanics_model.cc: auto m_it = this->mass->begin(Model::spatial_dimension);
+solid_mechanics/solid_mechanics_model.cc: auto m_end = this->mass->end(Model::spatial_dimension);
+solid_mechanics/solid_mechanics_model.cc: auto v_it = this->velocity->begin(Model::spatial_dimension);
+solid_mechanics/solid_mechanics_model.cc: } else if (this->getDOFManager().hasMatrix("M")) {
+solid_mechanics/solid_mechanics_model.cc: this->assembleMatrix("M");
+solid_mechanics/solid_mechanics_model.cc: this->getDOFManager().assembleMatMulVectToArray("displacement", "M",
+solid_mechanics/solid_mechanics_model.cc: *this->velocity, Mv);
+solid_mechanics/solid_mechanics_model.cc: make_view(*this->velocity, spatial_dimension))) {
+solid_mechanics/solid_mechanics_model.cc: if (this->method == _static) {
+solid_mechanics/solid_mechanics_model.cc: incrs_or_velos = this->displacement_increment.get();
+solid_mechanics/solid_mechanics_model.cc: incrs_or_velos = this->velocity.get();
+solid_mechanics/solid_mechanics_model.cc: auto nb_nodes = this->mesh.getNbNodes();
+solid_mechanics/solid_mechanics_model.cc: auto is_local_node = this->mesh.isLocalOrMasterNode(n);
+solid_mechanics/solid_mechanics_model.cc: // bool is_not_pbc_slave_node = !this->isPBCSlaveNode(n);
+solid_mechanics/solid_mechanics_model.cc: if (this->method != _static) {
+solid_mechanics/solid_mechanics_model.cc: work *= this->getTimeStep();
+solid_mechanics/solid_mechanics_model.cc: mat_element.element = this->getConstitutiveLawLocalNumbering()(element);
+solid_mechanics/solid_mechanics_model.cc: this->getConstitutiveLaw(element).getEnergy(energy_id, mat_element);
+solid_mechanics/solid_mechanics_model.cc: this->for_each_constitutive_law(
+solid_mechanics/solid_mechanics_model.cc: this->registerNewConstitutiveLaw(mat_name, mat_type, opt_param);
+solid_mechanics/material_inline_impl.hh: return (this->isFiniteDeformation() ? 3 : 1) * spatial_dimension *
+solid_mechanics/material_inline_impl.hh: this->getModel().getNbIntegrationPoints(elements);
+solid_mechanics/material_inline_impl.hh: this->getModel().getNbIntegrationPoints(elements);
+solid_mechanics/material_inline_impl.hh: if (this->isFiniteDeformation()) {
+solid_mechanics/material_inline_impl.hh: if (this->isFiniteDeformation()) {
+common/dof_manager/dof_manager_petsc.cc: this->mpi_communicator = mpi_comm;
+common/dof_manager/dof_manager_petsc.cc: this->mpi_communicator = PETSC_COMM_SELF;
+common/dof_manager/dof_manager_petsc.cc: auto & dof_data = this->getDOFDataTyped<DOFDataPETSc>(dof_id);
+common/dof_manager/dof_manager_petsc.cc: auto & A = this->getMatrix(mat.first);
+common/dof_manager/dof_manager_petsc.cc: return this->registerNonLinearSolver<NonLinearSolverPETSc>(*this, id, type);
+common/dof_manager/dof_manager_petsc.cc: return this->registerTimeStepSolver<TimeStepSolverDefault>(
+common/dof_manager/dof_manager_petsc.cc: return this->registerSparseMatrix<SparseMatrixPETSc>(*this, id, matrix_type);
+common/dof_manager/dof_manager_petsc.cc: return this->registerSparseMatrix<SparseMatrixPETSc>(id, matrix_to_copy_id);
+common/dof_manager/dof_manager_petsc.cc: return this->registerLumpedMatrix<SolverVectorPETSc>(*this, id);
+common/dof_manager/dof_manager_petsc.cc: return aka::as_type<SolverVectorPETSc>(*this->solution);
+common/dof_manager/dof_manager_petsc.cc: return aka::as_type<SolverVectorPETSc>(*this->solution);
+common/dof_manager/dof_manager_petsc.cc: return aka::as_type<SolverVectorPETSc>(*this->residual);
+common/dof_manager/dof_manager_petsc.cc: return aka::as_type<SolverVectorPETSc>(*this->residual);
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->setFallback(
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->setFallbackCohesiveValue(getDefaultCohesiveMaterial(model));
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: if (this->getFallbackCohesiveValue() == -1) {
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->setFallbackCohesiveValue(getDefaultCohesiveMaterial(this->model));
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: return this->getFallbackCohesiveValue();
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: return this->getFallbackCohesiveValue();
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->setFallback(std::make_shared<MeshDataMaterialSelector<std::string>>(
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: std::string material_name = this->material_index(facet);
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: return this->model.getMaterialIndex(material_name);
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->setFallback(std::make_shared<DefaultMaterialCohesiveSelector>(model));
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->getFallbackSelector()->setFallback(
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: this->mesh_data_id, model));
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: auto id1 = this->mesh.getData<std::string>(mesh_data_id, el1);
+solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc: id2 = this->mesh.getData<std::string>(mesh_data_id, el2);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc: auto & fe_engine = this->getFEEngine("FacetsFEEngine");
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc: const auto & fe_engine = this->getFEEngine("FacetsFEEngine");
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_parallel.cc: buffer << this->getConstitutiveLawByElement()(element);
+solid_mechanics/materials/material_elastic.cc: this->registerParam("lambda", lambda, _pat_readable,
+solid_mechanics/materials/material_elastic.cc: this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
+solid_mechanics/materials/material_elastic.cc: this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
+solid_mechanics/materials/material_elastic.cc: this->nu = 0.;
+solid_mechanics/materials/material_elastic.cc: this->updateInternalParameters();
+solid_mechanics/materials/material_elastic.cc: this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
+solid_mechanics/materials/material_elastic.cc: this->mu = this->E / (2 * (1 + this->nu));
+solid_mechanics/materials/material_elastic.cc: this->kpa = this->lambda + 2. / 3. * this->mu;
+solid_mechanics/materials/material_elastic.cc: this->was_stiffness_assembled = false;
+solid_mechanics/materials/material_elastic.cc: this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
+solid_mechanics/materials/material_elastic.cc: this->mu = this->E / (2 * (1 + this->nu));
+solid_mechanics/materials/material_elastic.cc: if (this->plane_stress) {
+solid_mechanics/materials/material_elastic.cc: this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu));
+solid_mechanics/materials/material_elastic.cc: this->kpa = this->lambda + 2. / 3. * this->mu;
+solid_mechanics/materials/material_elastic.cc: this->was_stiffness_assembled = false;
+solid_mechanics/materials/material_elastic.cc: if (not this->finite_deformation) {
+solid_mechanics/materials/material_elastic.cc: this->computeStressOnQuad(args);
+solid_mechanics/materials/material_elastic.cc: auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
+solid_mechanics/materials/material_elastic.cc: this->computeStressOnQuad(tuple::replace(args, "grad_u"_n = E));
+solid_mechanics/materials/material_elastic.cc: this->computeTangentModuliOnQuad(args);
+solid_mechanics/materials/material_elastic.cc: this->was_stiffness_assembled = true;
+solid_mechanics/materials/material_elastic.cc: return sqrt((lambda + 2 * mu) / this->rho);
+solid_mechanics/materials/material_elastic.cc: return sqrt(mu / this->rho);
+solid_mechanics/materials/material_elastic.cc: if (not this->finite_deformation) {
+solid_mechanics/materials/material_elastic.cc: zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+solid_mechanics/materials/material_elastic.cc: this->computePotentialEnergyOnQuad(args, epot);
+solid_mechanics/materials/material_elastic.cc: zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+solid_mechanics/materials/material_elastic.cc: auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
+solid_mechanics/materials/material_elastic.cc: this->computePotentialEnergyOnQuad(tuple::replace(args, "grad_u"_n = E),
+solid_mechanics/materials/material_elastic.cc: auto gradu_view = make_view<dim, dim>(this->gradu(type));
+solid_mechanics/materials/material_elastic.cc: auto stress_view = make_view<dim, dim>(this->stress(type));
+solid_mechanics/materials/material_elastic.cc: if (this->finite_deformation) {
+solid_mechanics/materials/material_elastic.cc: stress_view = make_view<dim, dim>((*this->piola_kirchhoff_2)(type));
+solid_mechanics/materials/material_elastic.cc: auto nb_quadrature_points = this->getFEEngine().getNbIntegrationPoints(type);
+solid_mechanics/materials/material_elastic.cc: if (this->finite_deformation) {
+solid_mechanics/materials/material_elastic.cc: auto E = this->template gradUToE<dim>(data["grad_u"_n]);
+solid_mechanics/materials/material_elastic.cc: this->computePotentialEnergyOnQuad(tuple::replace(data, "grad_u"_n = E),
+solid_mechanics/materials/material_elastic.cc: this->computePotentialEnergyOnQuad(data, data["Epot"_n]);
+solid_mechanics/materials/material_elastic.cc: return std::sqrt(this->E / this->rho);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->registerParam("area", area, _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->registerParam("pre_stress", pre_stress, _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->element_filter.initialize(this->emodel.getInterfaceMesh(),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: gradu_embedded = this->registerInternal("gradu_embedded", dim * dim,
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->registerInternal("pre_stress", 1, "EmbeddedInterfaceFEEngine");
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->initFilters();
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->allocBackgroundShapeDerivatives();
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->initBackgroundShapeDerivatives();
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->initDirectingCosines();
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: "bg_" + shaped_id, this->name),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: std::make_unique<ElementTypeMapArray<Idx>>(shaped_id, this->name),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: auto & elem_filter = this->element_filter(interface_type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: for (auto type : filter.elementTypes(this->spatial_dimension)) {
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: return array_size_per_bg_type(bgtype, this->ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: std::make_unique<ElementTypeMapArray<Real>>(shaped_id, this->name),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->element_filter.elementTypes(this->spatial_dimension)) {
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->element_filter(interface_type));
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: directing_cosines = this->registerInternal("directing_cosines", voigt_size,
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->assembleInternalForces(type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->computeStress(type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: auto & stress = this->stress(type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: auto & sigma_p = this->pre_stress(type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: const auto & elem_filter = this->element_filter(interface_type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->stress(interface_type, ghost_type),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: Array<Real> node_coordinates(this->element_filter(type, ghost_type).size(),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->emodel.getFEEngine().template extractNodalToElementField<Real>(
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: ghost_type, this->element_filter(type, ghost_type));
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: Array<Idx> & elem_filter = this->element_filter(interface_type, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->computeTangentModuli(interface_type, tangent_moduli, ghost_type);
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->computePotentialEnergyByElements();
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->element_filter.elementTypes(this->spatial_dimension)) {
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->potential_energy(type, _not_ghost), type, _not_ghost,
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->element_filter(type, _not_ghost));
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: this->gradu(interface_type, ghost_type),
+solid_mechanics/materials/material_embedded/material_reinforcement_tmpl.hh: make_view(this->directing_cosines(interface_type, ghost_type),
+solid_mechanics/materials/material_damage/material_anisotropic_damage.hh: "damage"_n = make_view<dim, dim>(this->damage(el_type, ghost_type)),
+solid_mechanics/materials/material_damage/material_anisotropic_damage.hh: make_view<dim, dim>(this->elastic_stress(el_type, ghost_type)),
+solid_mechanics/materials/material_damage/material_anisotropic_damage.hh: "epsilon_hat"_n = this->equivalent_strain(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_anisotropic_damage.hh: "TrD"_n = this->trace_damage(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_anisotropic_damage.hh: "TrD_n_1"_n = this->trace_damage.previous(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_phasefield.hh: this->effective_damage(el_type, ghost_type)));
+solid_mechanics/materials/material_damage/material_phasefield.hh: make_view(this->effective_damage(el_type, ghost_type)));
+solid_mechanics/materials/material_damage/material_marigo.cc: : MaterialDamage<dim>(model, id), Y(this->registerInternal("Y", 1)),
+solid_mechanics/materials/material_damage/material_marigo.cc: Yd(this->template registerInternal<Real, DefaultRandomInternalField>("Yd",
+solid_mechanics/materials/material_damage/material_marigo.cc: this->registerParam("Sd", Sd, Real(5000.), _pat_parsable | _pat_modifiable);
+solid_mechanics/materials/material_damage/material_marigo.cc: this->registerParam("epsilon_c", epsilon_c, Real(0.), _pat_parsable,
+solid_mechanics/materials/material_damage/material_marigo.cc: this->registerParam("Yc limit", yc_limit, false, _pat_internal,
+solid_mechanics/materials/material_damage/material_marigo.cc: this->registerParam("damage_in_y", damage_in_y, false, _pat_parsable,
+solid_mechanics/materials/material_damage/material_marigo.cc: this->registerParam("Yd", Yd, _pat_parsable, "Damaging energy threshold");
+solid_mechanics/materials/material_damage/material_marigo.cc: Yc = epsilon_c * this->E * epsilon_c / 2.;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.hh: // this->effective_damage(el_type, ghost_type)));
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.hh: // make_view(this->effective_damage(el_type, ghost_type)));
+solid_mechanics/materials/material_damage/material_marigo.hh: "Yd"_n = this->Yd(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_marigo.hh: "Y"_n = this->Y(el_type, ghost_type));
+solid_mechanics/materials/material_damage/material_damage_non_local.hh: for (auto type : this->getElementFilter().elementTypes(dim, ghost_type)) {
+solid_mechanics/materials/material_damage/material_damage_non_local.hh: auto & elem_filter = this->getElementFilter(type, ghost_type);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->registerParam("eta", eta, Real(0.), _pat_parsable, "eta");
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->registerParam("is_isotropic", is_isotropic, false,
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->damage.initialize(0);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: if (not this->finite_deformation) {
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->computeStressOnQuad(args);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->computeStressOnQuad(tuple::replace(args, "grad_u"_n = E));
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->dev_dim = 2;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: if (!this->plane_stress) {
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->dev_dim = 3;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: if (not this->finite_deformation) {
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->computeTangentModuliOnQuad(args);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc: this->computeTangentModuliOnQuad(tuple::replace(args, "grad_u"_n = E));
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: : Parent<dim>(model, id), damage(this->registerInternal("damage", 1)),
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: dissipated_energy(this->registerInternal("damage dissipated energy", 1)),
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: int_sigma(this->registerInternal("integral of sigma", 1)) {
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: this->computePotentialEnergy(el_type);
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: zip(getArguments(el_type), this->potential_energy(el_type),
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: this->dissipated_energy(el_type), this->int_sigma(el_type))) {
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: de += this->getFEEngine().integrate(
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: this->dissipated_energy(type, _not_ghost), type, _not_ghost,
+solid_mechanics/materials/material_damage/material_damage_tmpl.hh: this->getElementFilter(type, _not_ghost));
+solid_mechanics/materials/material_damage/material_mazars.hh: "K0"_n = this->K0(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_mazars.hh: broadcast(this->Ehat, this->damage(el_type, ghost_type).size()));
+solid_mechanics/materials/material_damage/material_marigo_non_local.hh: "Y"_n = this->Ynl(el_type, ghost_type));
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: : parent(model, id), Ehat(this->registerInternal("Ehat", 1)),
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: non_local_variable(this->registerInternal("non_local_variable", 1)) {
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: this->is_non_local = true;
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: this->registerParam("average_on_damage", this->damage_in_compute_stress,
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: if (this->damage_in_compute_stress) {
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: local = this->damage.getName();
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: local = this->Ehat.getName();
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: this->getModel().getNonLocalManager().registerNonLocalVariable(
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: this->getModel()
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: .getNeighborhood(this->name)
+solid_mechanics/materials/material_damage/material_mazars_non_local_tmpl.hh: if (this->damage_in_compute_stress) {
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: K0(this->template registerInternal<Real, DefaultRandomInternalField>("K0",
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->registerParam("K0", this->K0, _pat_parsable, "K0");
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->registerParam("At", this->At, Real(0.8), _pat_parsable, "At");
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->registerParam("Ac", this->Ac, Real(1.4), _pat_parsable, "Ac");
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->registerParam("Bc", this->Bc, Real(1900.), _pat_parsable, "Bc");
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->registerParam("Bt", this->Bt, Real(12000.), _pat_parsable, "Bt");
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->registerParam("beta", this->beta, Real(1.06), _pat_parsable, "beta");
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: if (not this->is_non_local) {
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: auto Cdiag = this->E * (1 - this->nu) / ((1 + this->nu) * (1 - 2 * this->nu));
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->lambda * (epsilon_princ(1) + epsilon_princ(2));
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->lambda * (epsilon_princ(0) + epsilon_princ(2));
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: this->lambda * (epsilon_princ(1) + epsilon_princ(0));
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: auto trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2));
+solid_mechanics/materials/material_damage/material_mazars_inline_impl.hh: auto epsilon_t = (1 + this->nu) / this->E * sigma_p(i) - trace_p;
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: MeshSegmentIntersector<dim, type> intersector(this->mesh, interface_mesh); \
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: const Int dim = this->mesh.getSpatialDimension();
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: this->primitive_mesh.getData<std::string>("physical_names",
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: auto segment = this->createSegment(el_connectivity);
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: for (auto type : this->mesh.elementTypes(dim, _not_ghost)) {
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: MeshSegmentIntersector<dim, type> intersector(this->mesh,
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: const auto & nodes = this->primitive_mesh.getNodes();
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: if (this->mesh.getSpatialDimension() == 2) {
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_intersector.cc: } else if (this->mesh.getSpatialDimension() == 3) {
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: if (this->damage_in_y) {
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: if (this->yc_limit) {
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: Y = std::min(Y, this->Yc);
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: if (not this->is_non_local) {
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: size += sizeof(Real) * this->getModel().getNbIntegrationPoints(elements);
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: this->packInternalFieldHelper(Yd, buffer, elements);
+solid_mechanics/materials/material_damage/material_marigo_inline_impl.hh: this->unpackInternalFieldHelper(Yd, buffer, elements);
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: damage(this->registerInternal("damage", dim * dim)),
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: elastic_stress(this->registerInternal("elastic_stress", dim * dim)),
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: equivalent_strain(this->registerInternal("equivalent_strain", 1)),
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: trace_damage(this->registerInternal("trace_damage", 1)) {
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: this->registerParam("Dc", Dc, _pat_parsable, "Critical damage");
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: this->trace_damage.initializeHistory();
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: epsilon = this->template gradUToEpsilon<dim>(grad_u);
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: auto kpa = this->kpa;
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: auto lambda = this->lambda;
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: this->E = 9 * kpa * (kpa - lambda) / (3 * kpa - lambda);
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: this->nu = lambda / (3 * kpa - lambda);
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: this->updateInternalParameters();
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: if (x > this->Dc) {
+solid_mechanics/materials/material_damage/material_anisotropic_damage_tmpl.hh: return this->Dc;
+solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh: Real kappa = this->lambda + 2. / Real(dim) * this->mu;
+solid_mechanics/materials/material_damage/material_phasefield_inline_impl.hh: this->mu * strain_dev.doubleDot(strain_dev);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: Real kappa = this->lambda + 2. / Real(dev_dim) * this->mu;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: 2. * this->mu * strain_dev;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: tangent(0, 0) = g_d_hyd * this->E;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: Real kappa = this->lambda + 2. / Real(dim) * this->mu;
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: auto Miiii = g_d_hyd * kappa + g_d * 2. * this->mu * (1. - 1. / Real(dev_dim));
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: [[maybe_unused]] auto Miijj = g_d_hyd * kappa - g_d * 2. * this->mu / Real(dev_dim);
+solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh: [[maybe_unused]] auto Mijij = g_d * this->mu;
+solid_mechanics/materials/material_damage/material_phasefield.cc: effective_damage(this->registerInternal("effective_damage", 1)) {
+solid_mechanics/materials/material_damage/material_phasefield.cc: this->registerParam("eta", eta, Real(0.), _pat_parsable, "eta");
+solid_mechanics/materials/material_damage/material_phasefield.cc: this->registerParam("is_hybrid", is_hybrid, false,
+solid_mechanics/materials/material_damage/material_phasefield.cc: if (this->is_hybrid) {
+solid_mechanics/materials/material_damage/material_phasefield.cc: if (this->is_hybrid) {
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh: this->damage_with_damage_rate =
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh: &(this->manager.registerWeightFunctionInternal("damage-rate"));
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh: (*this->damage_with_damage_rate)(q2.type, q2.ghost_type);
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function_inline_impl.hh: Real alpha = std::max(0., 1. - pow((r * r / this->R2), alphaexp));
+solid_mechanics/materials/material_damage/material_damage.hh: "damage"_n = this->damage(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_damage.hh: this->damage.previous(el_type, ghost_type));
+solid_mechanics/materials/material_damage/material_damage.hh: "damage"_n = this->damage(el_type, ghost_type),
+solid_mechanics/materials/material_damage/material_damage.hh: "previous_damage"_n = this->damage.previous(el_type, ghost_type));
+solid_mechanics/materials/material_damage/material_mazars_non_local.hh: "Ehat"_n = make_view(this->Ehat(el_type, ghost_type)));
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: Ynl(this->template registerInternal<Real>("Y non local", 1)) {
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: this->is_non_local = true;
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: this->getModel().getNonLocalManager().registerNonLocalVariable(
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: this->Y.getName(), Ynl.getName(), 1);
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: this->getModel()
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: .getNeighborhood(this->name)
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: auto && arguments = this->getArguments(el_type, ghost_type);
+solid_mechanics/materials/material_damage/material_marigo_non_local.cc: this->computeDamageAndStressOnQuad(data);
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh: auto & dam_array = (*this->damage)(q2.type, q2.ghost_type);
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh: Real alpha = std::max(0., 1. - r * r / this->R2);
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh: this->damage = &(this->manager.registerWeightFunctionInternal("damage"));
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh: return this->manager.getModel().getNbIntegrationPoints(elements) *
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh: *damage, buffer, elements, this->manager.getModel().getFEEngine());
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh: *damage, buffer, elements, this->manager.getModel().getFEEngine());
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc: this->model_type = ModelType::_embedded_model;
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc: this->setMaterialSelector(mat_sel_pointer);
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc: this->mesh.registerDumper<DumperParaview>("reinforcement", id);
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc: this->mesh.addDumpMeshToDumper("reinforcement", *interface_mesh, 1,
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc: // this->material_local_numbering(element) = index;
+solid_mechanics/solid_mechanics_model_embedded_interface/embedded_interface_model.cc: field = this->createElementalField(field_id, group_name, padding_flag, 1,
+solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh: Array<Real> & dam_array = (*this->damage)(q2.type, q2.ghost_type);
+solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh: Real Radius_init = this->R2;
+solid_mechanics/materials/weight_functions/damaged_weight_function_inline_impl.hh: this->damage = &(this->manager.registerWeightFunctionInternal("damage"));
+solid_mechanics/materials/weight_functions/damaged_weight_function.hh: this->init();
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh: this->registerParam<Real>("damage_limit",
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh: this->damage_limit_with_damage_rate, 1,
+solid_mechanics/materials/weight_functions/remove_damaged_with_damage_rate_weight_function.hh: this->init();
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: if (not this->is_non_local) {
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: Cdiag = this->E * (1 - this->nu) / ((1 + this->nu) * (1 - 2 * this->nu));
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: this->lambda * (epsilon_princ(1) + epsilon_princ(2));
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: this->lambda * (epsilon_princ(0) + epsilon_princ(2));
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: this->lambda * (epsilon_princ(1) + epsilon_princ(0));
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: Real trace_p = this->nu / this->E * (sigma_p(0) + sigma_p(1) + sigma_p(2));
+solid_mechanics/materials/material_damage/material_von_mises_mazars_inline_impl.hh: Real epsilon_t = (1 + this->nu) / this->E * sigma_p(i) - trace_p;
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->registerParam("lambda", lambda, _pat_readable,
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->registerParam("mu", mu, _pat_readable, "Second Lamé coefficient");
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->registerParam("kapa", kpa, _pat_readable, "Bulk coefficient");
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->finite_deformation = true;
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->updateInternalParameters();
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->updateInternalParameters();
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: zip(make_view<2, 2>(this->gradu(el_type, ghost_type)),
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: make_view<2, 2>((*this->piola_kirchhoff_2)(el_type, ghost_type)),
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: make_view<2, 2>(this->stress(el_type, ghost_type)),
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: make_view(this->third_axis_deformation(el_type, ghost_type)))) {
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: for (auto && args : this->getArguments(el_type, ghost_type)) {
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: AKANTU_DEBUG_ASSERT(this->plane_stress, "The third component of the strain "
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: this->computePotentialEnergyOnQuad(args, epot);
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: return std::sqrt((this->lambda + 2 * this->mu) / this->rho);
+solid_mechanics/materials/material_finite_deformation/material_neohookean.cc: return std::sqrt(this->mu / this->rho);
+solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh: return (this->lambda / 2. *
+solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh: (std::log(x) + std::log(this->C(0, 0) * this->C(1, 1) -
+solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh: Math::pow<2>(this->C(0, 1)))) +
+solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh: this->mu * (x - 1.));
+solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh: return (this->lambda / (2. * x) + this->mu);
+solid_mechanics/materials/material_finite_deformation/material_neohookean_inline_impl.hh: C33 = nr.solve(C33_NR("Neohookean_plan_stress", this->lambda, this->mu, C),
+solid_mechanics/materials/material_embedded/material_reinforcement.hh: * - this->spatial_dimension is always 1
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: this->registerParam("Plane_Stress", plane_stress, false, _pat_parsmod,
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: this->third_axis_deformation.setDefaultValue(1.);
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: if (this->plane_stress) {
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: if (this->plane_stress) {
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: AKANTU_DEBUG_ASSERT(this->finite_deformation,
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: for (auto && type : this->elementTypes(2, ghost_type)) {
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: this->computeCauchyStressPlaneStress(type, ghost_type);
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: this->registerInternal("third_axis_deformation", 1)) {
+solid_mechanics/materials/plane_stress_toolbox_tmpl.hh: this->initialize();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->implicitPred();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // displacement_tmp->copy(*(this->displacement));
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // velocity_tmp->copy(*(this->velocity));
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // acceleration_tmp->copy(*(this->acceleration));
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->updateResidual();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->assembleStiffnessMatrix();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // converged = this->testConvergence<criteria>(tolerance, error);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->assembleStiffnessMatrix();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->implicitCorr();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->updateResidual();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // converged = this->testConvergence<criteria>(tolerance, error);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // displacement_tmp = this->displacement;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->displacement = tmp_swap;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // velocity_tmp = this->velocity;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->velocity = tmp_swap;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // acceleration_tmp = this->acceleration;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->acceleration = tmp_swap;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->displacement->copy(*displacement_tmp);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->velocity->copy(*velocity_tmp);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive_inline_impl.hh:// // this->acceleration->copy(*acceleration_tmp);
+solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh: auto voigt_stress = this->C * voigt_strain;
+solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh: args["tangent_moduli"_n] = this->C;
+solid_mechanics/materials/material_elastic_linear_anisotropic_inline_impl.hh: AKANTU_DEBUG_ASSERT(this->symmetric,
+solid_mechanics/materials/material_thermal.hh: sigma = -this->E / (1. - 2. * this->nu) * this->alpha * deltaT;
+solid_mechanics/materials/material_thermal.hh: sigma = -this->E * this->alpha * deltaT;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: tmp_material_selector->setFallback(this->getConstitutiveLawSelector());
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->setConstitutiveLawSelector(tmp_material_selector);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->mesh.registerDumper<DumperParaview>("cohesive elements", id);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->mesh.addDumpMeshToDumper("cohesive elements", mesh,
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: if (this->mesh.isDistributed()) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->cohesive_synchronizer = std::make_unique<ElementSynchronizer>(
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->cohesive_synchronizer->split(synchronizer, [](auto && el) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->registerSynchronizer(*cohesive_synchronizer,
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->registerSynchronizer(*cohesive_synchronizer,
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->registerSynchronizer(*cohesive_synchronizer,
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->inserter = std::make_unique<CohesiveElementInserter>(
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->mesh, id + ":cohesive_element_inserter");
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->mesh.getDumper("cohesive elements").setTimeStep(time_step);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->is_extrinsic = smmc_options.is_extrinsic;
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->registerSynchronizer(*facet_stress_synchronizer,
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: auto && [section, is_empty] = this->getParserSection();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: auto & material_selector = this->getConstitutiveLawSelector();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: aka::as_type<MaterialCohesive>(this->getConstitutiveLaw(mat_index));
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->initAutomaticInsertion();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->insertIntrinsicElements();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->inserter->limitCheckFacets();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->updateFacetStressSynchronizer();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->resizeFacetStress();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->computeNormals();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->initStressInterpolation();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->inserter->limitCheckFacets();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->updateFacetStressSynchronizer();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->for_each_constitutive_law([&](auto && material) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->for_each_constitutive_law([&](auto && material) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: Mesh & mesh_facets = this->inserter->getMeshFacets();
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->getFEEngine("FacetsFEEngine")
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->getFEEngine("FacetsFEEngine")
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: Array<Real> & tangents = this->tangents(facet_type);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->for_each_constitutive_law([&](auto && material) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->synchronize(SynchronizationTag::_smmc_facets_stress);
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->for_each_constitutive_law([&](auto && material) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->for_each_constitutive_law([](auto && mat) {
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->facet_stress.initialize(getFEEngine("FacetsFEEngine"),
+solid_mechanics/solid_mechanics_model_cohesive/solid_mechanics_model_cohesive.cc: this->flattenAllRegisteredInternals(_ek_cohesive);
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: this->element_kind = _ek_cohesive;
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: this->internalInitialize(nb_component);
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: return this->registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: return this->registerInternal<Real, CohesiveRandomInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: this->spatial_dimension -= 1;
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: this->element_kind = _ek_regular;
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: this->internalInitialize(nb_component);
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: return this->registerInternal<Real, FacetInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh: return this->registerInternal<Real, FacetRandomInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field.hh: return aka::as_type<FacetInternalField>(this->shared_from_this());
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->registerParam("sigma_c", sigma_c, _pat_parsable | _pat_readable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->registerParam("delta_c", delta_c, Real(0.),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->getElementFilter().initialize(this->model->getMesh(),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: if (this->model->getIsExtrinsic()) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->getFacetFilter().initialize(this->model->getMeshFacets(),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: if (this->use_previous_delta_max) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->delta_max.initializeHistory();
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->opening.initializeHistory();
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->tractions.initializeHistory();
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.cc: this->model->getFEEngineClass<MyFEEngineCohesiveType>("CohesiveFEEngine");
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: "normal"_n = make_view<dim>(this->normals(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: "opening"_n = make_view<dim>(this->opening(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: make_view<dim>(this->tractions(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: make_view<dim>(this->contact_opening(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: make_view<dim>(this->contact_tractions(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: make_view<dim>(this->opening.previous(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: make_view<dim>(this->tractions.previous(element_type, ghost_type)),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: "delta_max"_n = this->delta_max(element_type, ghost_type),
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive.hh: "damage"_n = this->damage(element_type, ghost_type));
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh: this->getModel().getNbIntegrationPoints(elements,
+solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_inline_impl.hh: return Int(sizeof(Real)) * this->getModel().getNbIntegrationPoints(
+solid_mechanics/materials/weight_functions/stress_based_weight_function_inline_impl.hh: // Real rho_lc_2 = std::max(this->R2 * rho_2, min_rho_lc*min_rho_lc);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->normal_opening_norm = norm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->normal_opening = normal * this->normal_opening_norm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->tangential_opening = opening - normal_opening;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->tangential_opening_norm = this->tangential_opening.norm();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto delta = this->tangential_opening_norm * this->tangential_opening_norm *
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: penetration = this->normal_opening_norm / delta_c < -Math::getTolerance();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: if (not this->contact_after_breaking and Math::are_float_equal(damage, 1.)) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: contact_traction = this->normal_opening * this->penalty;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: contact_opening = this->normal_opening;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->normal_opening.zero();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: delta += this->normal_opening_norm * this->normal_opening_norm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: (this->tangential_opening * this->beta2_kappa + this->normal_opening) *
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->normal_opening_norm = opening.dot(normal);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->normal_opening = normal * normal_opening_norm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->tangential_opening = opening - normal_opening;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->tangential_opening_norm = tangential_opening.norm();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto delta = this->tangential_opening_norm * this->tangential_opening_norm *
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: if (not this->contact_after_breaking and Math::are_float_equal(damage, 1.)) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: Real sigma_c = this->sigma_c;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto && I = Eigen::Matrix<Real, dim, dim>::Identity() * this->beta2_kappa;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto && nn = (n_outer_n * (1. - this->beta2_kappa) + I) * t / delta;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto && mm = opening * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto && t_tilde = normal_opening * (1. - this->beta2_kappa2) + mm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_inline_impl.hh: auto && t_hat = normal_opening + this->beta2_kappa * tangential_opening;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc: this->registerParam("beta", beta, Real(0.), _pat_parsable, "Beta parameter");
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc: this->registerParam("exponential_penalty", exp_penalty, true, _pat_parsable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc: this->registerParam(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_exponential.cc: // this->initInternalArray(delta_max, 1, _ek_cohesive);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->registerParam("mu", mu_max, Real(0.), _pat_parsable | _pat_readable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->registerParam("penalty_for_friction", friction_penalty, Real(0.),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: if (not this->penetration) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: Real tau_max = mu * this->penalty * (std::abs(this->normal_opening_norm));
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: std::abs(this->tangential_opening_norm - res_sliding_prev);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: if ((this->tangential_opening_norm - res_sliding_prev) < 0.0) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: tau * this->tangential_opening / this->tangential_opening_norm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: res_sliding = this->tangential_opening_norm;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->tangential_opening_norm - (std::abs(tau) / friction_penalty);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: if (not this->model->isDefaultSolverExplicit()) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->delta_max(el_type, ghost_type)
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: .copy(this->delta_max.previous(el_type, ghost_type));
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: this->computeTangentTractionOnQuad(tangent, args);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: if (not this->penetration) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: mu * this->penalty * (std::abs(previous_normal_opening_norm));
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: Real delta_sliding_norm = std::abs(this->tangential_opening_norm -
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_friction.cc: Real tau = std::min(this->friction_penalty * delta_sliding_norm, tau_max);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh: "sigma_c"_n = this->sigma_c_eff(element_type, ghost_type),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh: "delta_c"_n = this->delta_c_eff(element_type, ghost_type),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.hh: make_view<dim>(this->insertion_stress(element_type, ghost_type)));
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->registerParam("delta_0", delta_0, Real(0.),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->sigma_c_eff.setRandomDistribution(this->sigma_c.getRandomParameter());
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->delta_max.setDefaultValue(delta_0);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->insertion_stress.setDefaultValue(0);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->delta_max.reset();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->insertion_stress.reset();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: if (!Math::are_float_equal(this->volume_s, 0.)) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: auto nb_quad_per_element = this->fem_cohesive.getNbIntegrationPoints(type);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: make_view(this->sigma_c_eff(type), nb_quad_per_element).begin();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: make_view(this->delta_c_eff(type), nb_quad_per_element).begin();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: delta_c_vec(q) = 2 * this->G_c / sigma_c_vec(q);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: auto base_sigma_c = Real(this->sigma_c_eff);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: const auto & mesh_facets = this->model->getMeshFacets();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: const auto & fe_engine = this->model->getFEEngine();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: std::pow(this->volume_s / volume, 1. / this->m_s) +
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: for (auto && data : zip(this->damage(el_type, ghost_type),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->delta_max(el_type, ghost_type),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_bilinear.cc: this->delta_c_eff(el_type, ghost_type))) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: delta_prec(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: K_plus(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: K_minus(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: T_1d(this->template registerInternal<Real, CohesiveInternalField>("T_1d",
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->template registerInternal<bool, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->registerParam("delta_f", delta_f, Real(-1.),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->registerParam("progressive_delta_f", progressive_delta_f, false,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->registerParam("count_switches", count_switches, false,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->registerParam(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: delta_f = this->delta_c_eff;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: } else if (delta_f < this->delta_c_eff) {
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->template registerInternal<Int, CohesiveInternalField>("switches", 1);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: switches = this->template getSharedPtrInternal<Int, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->template getSharedPtrInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->tractions(el_type, ghost_type).begin(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: auto opening_it = this->opening(el_type, ghost_type).begin(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->contact_tractions(el_type, ghost_type).begin(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->contact_opening(el_type, ghost_type).begin(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: auto normal_it = this->normals(el_type, ghost_type).begin(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->tractions(el_type, ghost_type).end(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: const Array<Real> & sigma_c_array = this->sigma_c_eff(el_type, ghost_type);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: Array<Real> & delta_max_array = this->delta_max(el_type, ghost_type);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: const Array<Real> & delta_c_array = this->delta_c_eff(el_type, ghost_type);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: Array<Real> & damage_array = this->damage(el_type, ghost_type);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: this->insertion_stress(el_type, ghost_type).begin(spatial_dimension);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: if (not this->contact_after_breaking and
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: *contact_traction_it *= this->penalty;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_fatigue.cc: *traction_it *= this->beta2_kappa;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: delta_n_max(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: delta_t_max(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: damage_n(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: damage_t(this->template registerInternal<Real, CohesiveInternalField>(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: this->registerParam(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto traction_it = this->tractions(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto traction_end = this->tractions(el_type, ghost_type).end(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto opening_it = this->opening(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: this->contact_tractions(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: this->contact_opening(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto normal_it = this->normals(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: this->insertion_stress(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: if (not this->contact_after_breaking and
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: *contact_traction_it = normal_opening * this->penalty;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: shear_traction = tangential_opening * this->beta2_kappa * *sigma_c_it /
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto normal_it = this->normals(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto opening_it = this->opening(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto sigma_c_it = this->sigma_c_eff(el_type, ghost_type).begin();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto delta_c_it = this->delta_c_eff(el_type, ghost_type).begin();
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: this->contact_opening(el_type, ghost_type).begin(dim);
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: tangential_opening_norm * tangential_opening_norm * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: if (not this->contact_after_breaking and
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: *tangent_it = n_outer_n * this->penalty;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: normal_opening * (1. - this->beta2_kappa2) +
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: *opening_it * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto && Delta_tilde = normal_opening * (delta_c2_R2 - this->beta2_kappa2) +
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: *opening_it * this->beta2_kappa2;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear_uncoupled.cc: auto && Delta_hat = tangential_opening * this->beta2_kappa;
+solid_mechanics/materials/material_elastic_inline_impl.hh: sigma(0, 0) = this->E * grad_u(0, 0) + sigma_th;
+solid_mechanics/materials/material_elastic_inline_impl.hh: tangent(0, 0) = this->E;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("beta", beta, Real(0.), _pat_parsable | _pat_readable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("G_c", G_c, Real(0.), _pat_parsable | _pat_readable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("penalty", penalty, Real(0.),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("volume_s", volume_s, Real(0.),
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("m_s", m_s, Real(1.), _pat_parsable | _pat_readable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("kappa", kappa, Real(1.), _pat_parsable | _pat_readable,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam(
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("max_quad_stress_insertion", max_quad_stress_insertion,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->registerParam("recompute", recompute, false,
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->use_previous_delta_max = true;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: Real sigma_c = this->sigma_c;
+solid_mechanics/solid_mechanics_model_cohesive/materials/constitutive_laws/material_cohesive_linear.cc: this->computeTractionOnQuad(args);
+solid_mechanics/materials/material_thermal.cc: delta_T(this->registerInternal("delta_T", 1)),
+solid_mechanics/materials/material_thermal.cc: sigma_th(this->registerInternal("sigma_th", 1)) {
+solid_mechanics/materials/material_thermal.cc: this->registerParam("E", E, Real(0.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_thermal.cc: this->registerParam("nu", nu, Real(0.5), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_thermal.cc: this->registerParam("alpha", alpha, Real(0.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_thermal.cc: this->registerParam("delta_T", delta_T, _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh: this->registerParam("damage_limit", this->damage_limit, 1., _pat_parsable,
+solid_mechanics/materials/weight_functions/remove_damaged_weight_function.hh: this->init();
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->dir_vecs.emplace_back(std::make_unique<Vector<Real, dim>>());
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: auto && n = *this->dir_vecs.back();
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->registerParam("n" + std::to_string(i + 1), *(this->dir_vecs.back()),
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: if (this->symmetric) {
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->registerParam(param, this->Cprime(i, j), Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: if (this->symmetric) {
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->Cprime(j, i) = this->Cprime(i, j);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->rotateCprime();
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->C.eig(this->eigC);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->was_stiffness_assembled = false;
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->Cprime(i, j) = this->Cprime(i - diff, j);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->Cprime(i, j) = this->Cprime(i, j - diff);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: auto && rot_vec = this->rot_mat(j);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: rot_vec = *this->dir_vecs[j];
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: v1.block<Dim, 1>(0, 0) = this->rot_mat(0);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: v2.block<Dim, 1>(0, 0) = this->rot_mat(1);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: Vector<Real, 3> v1 = this->rot_mat(0);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: Vector<Real, 3> v2 = this->rot_mat(1);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: Vector<Real, 3> v3 = this->rot_mat(2);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: rotator(I, J) = this->rot_mat(k, i) * this->rot_mat(l, j);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: revrotor(I, J) = this->rot_mat(i, k) * this->rot_mat(j, l);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->C(i, j) = Cfull(i, j);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->computeStressOnQuad(data);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->computeTangentModuliOnQuad(args);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->was_stiffness_assembled = true;
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: AKANTU_DEBUG_ASSERT(!this->finite_deformation,
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->computePotentialEnergyOnQuad(std::get<0>(args), std::get<1>(args));
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: const auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: auto gradu_view = make_view<dim, dim>(this->gradu(type));
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: auto stress_view = make_view<dim, dim>(this->stress(type));
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: this->computePotentialEnergyOnQuad(data, data["Epot"_n]);
+solid_mechanics/materials/material_elastic_linear_anisotropic.cc: return std::sqrt(this->eigC(0) / rho);
+solid_mechanics/materials/plane_stress_toolbox.hh: "C33"_n = broadcast(C33, this->stress(el_type, ghost_type).size()));
+solid_mechanics/materials/plane_stress_toolbox.hh: "C33"_n = broadcast(C33, this->stress(el_type, ghost_type).size()));
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("E1", E1, Real(0.), _pat_parsmod, "Young's modulus (n1)");
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("E2", E2, Real(0.), _pat_parsmod, "Young's modulus (n2)");
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("nu12", nu12, Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("G12", G12, Real(0.), _pat_parsmod, "Shear modulus (12)");
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("E3", E3, Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("nu13", nu13, Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("nu23", nu23, Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("G13", G13, Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->registerParam("G23", G23, Real(0.), _pat_parsmod,
+solid_mechanics/materials/material_elastic_orthotropic.cc: AKANTU_DEBUG_ASSERT(not this->finite_deformation,
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->C.zero();
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime.zero();
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(0, 0) = E1 * (1 - nu23 * nu32) * Gamma;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(1, 1) = E2 * (1 - nu13 * nu31) * Gamma;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(2, 2) = E3 * (1 - nu12 * nu21) * Gamma;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(1, 0) = this->Cprime(0, 1) = E1 * (nu21 + nu31 * nu23) * Gamma;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(2, 0) = this->Cprime(0, 2) = E1 * (nu31 + nu21 * nu32) * Gamma;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(2, 1) = this->Cprime(1, 2) = E2 * (nu32 + nu12 * nu31) * Gamma;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(3, 3) = G23;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(4, 4) = G13;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(5, 5) = G12;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->Cprime(2, 2) = G12;
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->rotateCprime();
+solid_mechanics/materials/material_elastic_orthotropic.cc: this->C.eig(this->eigC);
+diffusion_model/heat_transfer_model.hh: [[nodiscard]] Array<Real> & getTemperature() { return this->getDiffusion(); }
+diffusion_model/heat_transfer_model.hh: return this->getDiffusion();
+diffusion_model/heat_transfer_model.hh: return this->getDiffusionRelease();
+diffusion_model/heat_transfer_model.hh: return this->getDiffusionRate();
+diffusion_model/heat_transfer_model.hh: return this->getExternalFlow();
+diffusion_model/heat_transfer_model.hh: return this->getExternalFlow();
+diffusion_model/heat_transfer_model.hh: return this->getInternalFlow();
+diffusion_model/heat_diffusion.cc: this->registerParam("density", density, _pat_parsmod);
+diffusion_model/heat_diffusion.cc: this->registerParam("conductivity", conductivity, _pat_parsmod);
+diffusion_model/heat_diffusion.cc: this->registerParam("conductivity_variation", conductivity_variation, 0.,
+diffusion_model/heat_diffusion.cc: this->registerParam("temperature_reference", T_ref, 0., _pat_parsmod);
+diffusion_model/heat_diffusion.cc: this->registerParam("capacity", capacity, _pat_parsmod);
+diffusion_model/heat_diffusion.cc: this->diffusivity.set(conductivity);
+diffusion_model/heat_diffusion.cc: this->computeDiffusivityOnQuadPoints(type, ghost_type);
+diffusion_model/heat_diffusion.cc: auto temperature_release = this->getHandler().getDiffusionRelease();
+diffusion_model/heat_diffusion.cc: auto & diffusivity_release = this->diffusivity.getRelease(type, ghost_type);
+diffusion_model/heat_diffusion.cc: this->getFEEngine().interpolateOnIntegrationPoints(
+diffusion_model/heat_diffusion.cc: zip(make_view<dim, dim>(this->diffusivity(type, ghost_type)),
+diffusion_model/heat_diffusion.cc: Real min_dt = 2. * element_size * element_size / 4. * this->density *
+diffusion_model/heat_diffusion.cc: this->getFEEngine().interpolateOnIntegrationPoints(
+diffusion_model/heat_diffusion.cc: this->getFEEngine().interpolateOnIntegrationPoints(
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: edis += 0.5 * g_c_quad * this->l0 * grad_d[i] * grad_d[i];
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: edis += g_c_quad * dam * dam / (2. * this->l0);
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: dam_energy_quad = 2.0 * phi_quad + g_c_quad / this->l0;
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: Real kpa = this->lambda + 2. * this->mu / Real(dev_dim);
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: this->mu * strain_dev.doubleDot(strain_dev);
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: phi_quad = 0.5 * this->lambda * trace * trace +
+phase_field/phasefields/phasefield_quadratic_inline_impl.hh: this->mu * strain_quad.doubleDot(strain_quad);
+phase_field/phasefields/phasefield_quadratic.cc: this->gamma = Real(this->g_c) / this->l0 * (1. / (tol_ir * tol_ir) - 1.);
+phase_field/phasefields/phasefield_quadratic.cc: this->dev_dim = dim;
+phase_field/phasefields/phasefield_quadratic.cc: if (dim == 2 && !this->plane_stress) {
+phase_field/phasefields/phasefield_quadratic.cc: this->dev_dim = 3;
+phase_field/phasefields/phasefield_quadratic.cc: zip(make_view(this->damage_energy(type, _not_ghost), dim, dim),
+phase_field/phasefields/phasefield_quadratic.cc: this->g_c(type, _not_ghost))) {
+phase_field/phasefields/phasefield_quadratic.cc: Matrix<Real>::Identity(dim, dim) * std::get<1>(tuple) * this->l0;
+phase_field/phasefields/phasefield_quadratic.cc: if (this->isotropic) {
+phase_field/phasefields/phasefield_quadratic.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_quadratic.cc: make_view(this->strain(el_type, ghost_type), dim, dim))) {
+phase_field/phasefields/phasefield_quadratic.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_quadratic.cc: make_view(this->strain(el_type, ghost_type), dim, dim))) {
+phase_field/phasefields/phasefield_quadratic.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_quadratic.cc: this->driving_force(el_type, ghost_type),
+phase_field/phasefields/phasefield_quadratic.cc: this->damage_energy_density(el_type, ghost_type),
+phase_field/phasefields/phasefield_quadratic.cc: this->damage_on_qpoints(el_type, _not_ghost),
+phase_field/phasefields/phasefield_quadratic.cc: make_view(this->driving_energy(el_type, ghost_type), dim),
+phase_field/phasefields/phasefield_quadratic.cc: make_view(this->damage_energy(el_type, ghost_type), dim, dim),
+phase_field/phasefields/phasefield_quadratic.cc: make_view(this->gradd(el_type, ghost_type), dim),
+phase_field/phasefields/phasefield_quadratic.cc: this->g_c(el_type, ghost_type),
+phase_field/phasefields/phasefield_quadratic.cc: this->damage_on_qpoints.previous(el_type, ghost_type))) {
+phase_field/phasefields/phasefield_quadratic.cc: this->gamma * std::min(Real(0.), dam_on_quad - dam_prev_quad);
+phase_field/phasefields/phasefield_quadratic.cc: dam_energy_density_quad += this->gamma * (dam_on_quad < dam_prev_quad);
+phase_field/phasefields/phasefield_quadratic.cc: for (auto && tuple : zip(this->dissipated_energy(el_type, _not_ghost),
+phase_field/phasefields/phasefield_quadratic.cc: this->damage_on_qpoints(el_type, _not_ghost),
+phase_field/phasefields/phasefield_quadratic.cc: make_view(this->gradd(el_type, _not_ghost), dim),
+phase_field/phasefields/phasefield_quadratic.cc: this->g_c(el_type, _not_ghost))) {
+phase_field/phasefields/phasefield_quadratic.cc: this->computeDissipatedEnergyOnQuad(std::get<1>(tuple), std::get<2>(tuple),
+phase_field/phasefields/phasefield_quadratic.cc: auto gradd_it = this->gradd(type).begin(dim);
+phase_field/phasefields/phasefield_quadratic.cc: auto gradd_end = this->gradd(type).begin(dim);
+phase_field/phasefields/phasefield_quadratic.cc: auto damage_it = this->damage_on_qpoints(type).begin();
+phase_field/phasefields/phasefield_quadratic.cc: auto g_c_it = this->g_c(type).begin();
+phase_field/phasefields/phasefield_quadratic.cc: auto & fem = this->getFEEngine();
+phase_field/phasefields/phasefield_quadratic.cc: this->computeDissipatedEnergyOnQuad(*damage_it, *gradd_it, *edis_quad,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh: Real dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh: return ((this->previous_dt == dt)
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh: ? (!(this->previous_dt == dt)) * (this->was_stiffness_assembled)
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh: : (!(this->previous_dt == dt)));
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.hh: // return (!(this->previous_dt == dt));
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: stress_dev(this->registerInternal("stress_dev", dim * dim)),
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: history_integral(this->registerInternal("history_integral", dim * dim)),
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: dissipated_energy(this->registerInternal("dissipated_energy", 1)) {
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: this->registerParam("Eta", eta, Real(1.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: this->registerParam("Ev", Ev, Real(1.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: this->registerParam("Einf", E_inf, Real(1.), _pat_readable,
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: E_inf = this->E - this->Ev;
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: for (auto && args : this->getArguments(el_type, ghost_type)) {
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: dev_s = 2 * this->mu *
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: Real dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto gamma_inf = E_inf / this->E;
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto gamma_v = Ev / this->E;
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto && arguments = this->getArguments(el_type, ghost_type);
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto epsilon_d = this->template gradUToEpsilon<dim>(grad_u);
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: Matrix<Real, dim, dim>::Identity() * gamma_inf * this->kpa * Theta;
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto s = 2 * this->mu * epsilon_d;
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: this->updateDissipatedEnergy(el_type, ghost_type);
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto gamma_v = Ev / this->E;
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto alpha = 1. / (2. * this->mu * gamma_v);
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: zip(this->getArguments(el_type, ghost_type),
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: this->getElementFilter(type, _not_ghost));
+solid_mechanics/materials/material_viscoelastic/material_standard_linear_solid_deviatoric.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: this->registerParam("phi", phi, Real(0.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: this->registerParam("fc", fc, Real(1.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: this->registerParam("radial_return", radial_return_mapping, bool(true),
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: Real phi_radian = this->phi * M_PI / 180.;
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: this->alpha = (6. * sin(phi_radian)) / (3. - sin(phi_radian));
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: Real cohesion = this->fc * (1. - sin(phi_radian)) / (2. * cos(phi_radian));
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: this->k = (6. * cohesion * cos(phi_radian)) / (3. - sin(phi_radian));
+solid_mechanics/materials/material_plastic/material_drucker_prager.cc: if (this->finite_deformation) {
+solid_mechanics/materials/material_plastic/material_plastic.hh: "iso_hardening"_n = make_view(this->iso_hardening(el_type, ghost_type)),
+solid_mechanics/materials/material_plastic/material_plastic.hh: make_view(this->iso_hardening.previous(el_type, ghost_type)),
+solid_mechanics/materials/material_plastic/material_plastic.hh: make_view<dim, dim>(this->inelastic_strain(el_type, ghost_type)),
+solid_mechanics/materials/material_plastic/material_plastic.hh: this->inelastic_strain.previous(el_type, ghost_type)));
+solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh: return this->alpha * sigma.trace() - this->k;
+solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh: if (above_threshold(k, alpha) and this->alpha > 0) {
+solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh: sigma_guess += -projection_error * 1. / this->alpha *
+solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh: bool initial_yielding = (this->computeYieldFunction(sigma_tr) > 0);
+solid_mechanics/materials/material_plastic/material_drucker_prager_inline_impl.hh: this->computeGradientAndPlasticMultplier(sigma_tr, dp, gradient_f,
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc: if (this->finite_deformation) { // Finite deformation
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc: make_view<dim, dim>((*this->green_strain)(el_type, ghost_type)))) {
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening.cc: this->was_stiffness_assembled = true;
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: ((sigma_tr_dev_eff - iso_hardening - this->sigma_y) > 0);
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: ? (sigma_tr_dev_eff - this->sigma_y - previous_iso_hardening) /
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: (3 * this->mu + this->h)
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: iso_hardening = previous_iso_hardening + this->h * dp;
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: ((cauchy_stress_dev_eff - iso_hardening - this->sigma_y) > 0);
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: this->sigma_y) > Math::getTolerance()) {
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: d_dp = (cauchy_stress_dev_eff - 3. * this->mu * dp - iso_hardening -
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: this->sigma_y) /
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: (3. * this->mu + this->h);
+solid_mechanics/materials/material_plastic/material_linear_isotropic_hardening_inline_impl.hh: iso_hardening = iso_hardening_t + this->h * dp;
+solid_mechanics/materials/material_plastic/material_plastic.cc: iso_hardening(this->registerInternal("iso_hardening", 1)),
+solid_mechanics/materials/material_plastic/material_plastic.cc: inelastic_strain(this->registerInternal("inelastic_strain", dim * dim)),
+solid_mechanics/materials/material_plastic/material_plastic.cc: plastic_energy(this->registerInternal("plastic_energy", 1)),
+solid_mechanics/materials/material_plastic/material_plastic.cc: d_plastic_energy(this->registerInternal("d_plastic_energy", 1)) {
+solid_mechanics/materials/material_plastic/material_plastic.cc: this->registerParam("h", h, Real(0.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_plastic/material_plastic.cc: this->registerParam("sigma_y", sigma_y, Real(0.),
+solid_mechanics/materials/material_plastic/material_plastic.cc: this->iso_hardening.initializeHistory();
+solid_mechanics/materials/material_plastic/material_plastic.cc: this->inelastic_strain.initializeHistory();
+solid_mechanics/materials/material_plastic/material_plastic.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_plastic/material_plastic.cc: this->getElementFilter().elementTypes(dim, _not_ghost)) {
+solid_mechanics/materials/material_plastic/material_plastic.cc: this->getElementFilter(type, _not_ghost));
+solid_mechanics/materials/material_plastic/material_plastic.cc: zip(getArguments(el_type), this->potential_energy(el_type))) {
+solid_mechanics/materials/material_plastic/material_plastic.cc: "pe"_n = this->plastic_energy(el_type),
+solid_mechanics/materials/material_plastic/material_plastic.cc: "wp"_n = this->d_plastic_energy(el_type))) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: dissipated_energy(this->registerInternal("dissipated_energy", 1)),
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: mechanical_work(this->registerInternal("mechanical_work", 1)) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->registerParam("Einf", Einf, Real(1.), _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->registerParam("previous_dt", previous_dt, Real(0.), _pat_readable,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->registerParam("Eta", Eta, _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->registerParam("Ev", Ev, _pat_parsable | _pat_modifiable,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->E = Einf + Ev.lpNorm<1>();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: AKANTU_DEBUG_ASSERT(this->Eta.size() == this->Ev.size(),
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: !this->finite_deformation,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->registerInternal("sigma_v", stress_size * this->Ev.size());
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->registerInternal("epsilon_v", stress_size * this->Ev.size());
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->sigma_v = this->getSharedPtrInternal("sigma_v");
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->epsilon_v = this->getSharedPtrInternal("epsilon_v");
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: [[maybe_unused]] auto pre_mult = 1 / (1 + this->nu) / (1 - 2 * this->nu);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: [[maybe_unused]] auto Miiii = pre_mult * (1 - this->nu);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: [[maybe_unused]] auto Miijj = pre_mult * this->nu;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: [[maybe_unused]] auto Mijij = pre_mult * 0.5 * (1 - 2 * this->nu);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: [[maybe_unused]] auto Diijj = -this->nu;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: [[maybe_unused]] auto Dijij = (2 + 2 * this->nu);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->Einf * this->C * voigt_current_strain;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->C * (voigt_current_strain - voigt_previous_strain);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (auto && [Eta, Ev, sigma] : zip(this->Eta, this->Ev, args["sigma_v"_n])) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: zip(getArguments(el_type), this->potential_energy(el_type),
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: make_view((*this->epsilon_v)(el_type), dim, dim, Eta.size()))) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->computePotentialEnergyOnQuad(args["grad_u"_n], epot,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->Einf * this->C * voigt_strain;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (Int k = 0; k < this->Eta.size(); ++k) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: if (this->update_variable_flag) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (const auto & el_type : this->getElementFilter().elementTypes(
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->updateDissipatedEnergy(el_type);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (Idx k = 0; k < this->Eta.size(); ++k) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto lambda = this->Eta(k) / this->Ev(k);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real E_ef_v = this->Ev(k);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: exp_dt_lambda * voigt_sigma_v + E_ef_v * this->C * voigt_delta_strain;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: voigt_epsilon_v = 1 / Ev(k) * this->D * voigt_sigma_v;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real E_ef = this->Einf;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real lambda = this->Eta(k) / this->Ev(k);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: E_ef += this->Ev(k);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: E_ef += (1 - exp_dt_lambda) * this->Ev(k) * lambda / dt;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->previous_dt = dt;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->computeTangentModuliOnQuad(tangent);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->was_stiffness_assembled = true;
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (const auto & el_type : this->getElementFilter().elementTypes()) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: make_view((*this->epsilon_v)(el_type), dim, dim, Eta.size()))) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->computePotentialEnergy(el_type);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: zip(getArguments(el_type), this->potential_energy(el_type),
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->dissipated_energy(el_type), this->mechanical_work(el_type))) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: Real dt = this->getModel().getTimeStep();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: de += fem.integrate(this->dissipated_energy(type, _not_ghost), type,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: _not_ghost, this->getElementFilter(type, _not_ghost));
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: make_view(this->dissipated_energy(element.type), nb_quadrature_points)
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: mat_element.element = this->getElementFilter()(element);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (auto && type : this->getElementFilter().elementTypes(dim)) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: mw += fem.integrate(this->mechanical_work(type), type, _not_ghost,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: this->getElementFilter(type, _not_ghost));
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto it = make_view(this->mechanical_work(element.type), nb_quadrature_points)
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: mat_element.element = this->getElementFilter()(element);
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: epot += fem.integrate(this->potential_energy(type, _not_ghost), type,
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: _not_ghost, this->getElementFilter(type, _not_ghost));
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: auto & fem = this->getFEEngine();
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: make_view(this->potential_energy(element.type), nb_quadrature_points)
+solid_mechanics/materials/material_viscoelastic/material_viscoelastic_maxwell.cc: mat_element.element = this->getElementFilter()(element);
+phase_field/phasefields/phasefield_linear.cc: this->gamma = Real(this->g_c) / this->l0 * 27. / (64. * tol_ir * tol_ir);
+phase_field/phasefields/phasefield_linear.cc: this->dev_dim = dim;
+phase_field/phasefields/phasefield_linear.cc: if (dim == 2 && !this->plane_stress) {
+phase_field/phasefields/phasefield_linear.cc: this->dim = 3;
+phase_field/phasefields/phasefield_linear.cc: zip(make_view(this->damage_energy(type, _not_ghost), dim, dim),
+phase_field/phasefields/phasefield_linear.cc: this->g_c(type, _not_ghost))) {
+phase_field/phasefields/phasefield_linear.cc: d.eye(3. / 4. * std::get<1>(tuple) * this->l0);
+phase_field/phasefields/phasefield_linear.cc: if (this->isotropic) {
+phase_field/phasefields/phasefield_linear.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_linear.cc: make_view(this->strain(el_type, ghost_type), dim, dim))) {
+phase_field/phasefields/phasefield_linear.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_linear.cc: make_view(this->strain(el_type, ghost_type), dim, dim))) {
+phase_field/phasefields/phasefield_linear.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_linear.cc: this->driving_force(el_type, ghost_type),
+phase_field/phasefields/phasefield_linear.cc: this->damage_energy_density(el_type, ghost_type),
+phase_field/phasefields/phasefield_linear.cc: this->damage_on_qpoints(el_type, _not_ghost),
+phase_field/phasefields/phasefield_linear.cc: make_view(this->driving_energy(el_type, ghost_type), dim),
+phase_field/phasefields/phasefield_linear.cc: make_view(this->damage_energy(el_type, ghost_type), dim, dim),
+phase_field/phasefields/phasefield_linear.cc: make_view(this->gradd(el_type, ghost_type), dim),
+phase_field/phasefields/phasefield_linear.cc: this->g_c(el_type, ghost_type),
+phase_field/phasefields/phasefield_linear.cc: this->damage_on_qpoints.previous(el_type, ghost_type))) {
+phase_field/phasefields/phasefield_linear.cc: this->gamma * std::min(Real(0.), dam_on_quad - dam_prev_quad);
+phase_field/phasefields/phasefield_linear.cc: 3 * g_c_quad / (8 * this->l0) + penalization;
+phase_field/phasefields/phasefield_linear.cc: dam_energy_density_quad += this->gamma * (dam_on_quad < dam_prev_quad);
+phase_field/phasefields/phasefield_linear.cc: zip(this->dissipated_energy(el_type, _not_ghost),
+phase_field/phasefields/phasefield_linear.cc: this->damage_on_qpoints(el_type, _not_ghost),
+phase_field/phasefields/phasefield_linear.cc: this->damage_on_qpoints.previous(el_type, _not_ghost),
+phase_field/phasefields/phasefield_linear.cc: make_view(this->gradd(el_type, _not_ghost), dim),
+phase_field/phasefields/phasefield_linear.cc: this->g_c(el_type, _not_ghost))) {
+phase_field/phasefields/phasefield_linear.cc: this->computeDissipatedEnergyOnQuad(std::get<1>(tuple), std::get<2>(tuple),
+phase_field/phasefields/phasefield_linear.cc: auto gradd_it = this->gradd(type).begin(dim);
+phase_field/phasefields/phasefield_linear.cc: auto gradd_end = this->gradd(type).begin(dim);
+phase_field/phasefields/phasefield_linear.cc: auto damage_it = this->damage_on_qpoints(type).begin();
+phase_field/phasefields/phasefield_linear.cc: auto damage_prev_it = this->damage_on_qpoints.previous(type).begin();
+phase_field/phasefields/phasefield_linear.cc: auto g_c_it = this->g_c(type).begin();
+phase_field/phasefields/phasefield_linear.cc: auto & fem = this->getFEEngine();
+phase_field/phasefields/phasefield_linear.cc: this->computeDissipatedEnergyOnQuad(*damage_it, *damage_prev_it, *gradd_it,
+phase_field/phasefields/phasefield_linear.cc: for (auto & dam : this->model.getDamage()) {
+phase_field/phasefields/phasefield_exponential.cc: this->dev_dim = dim;
+phase_field/phasefields/phasefield_exponential.cc: if (dim == 2 && !this->plane_stress) {
+phase_field/phasefields/phasefield_exponential.cc: this->dev_dim = 3;
+phase_field/phasefields/phasefield_exponential.cc: zip(make_view<dim, dim>(this->damage_energy(type, _not_ghost)),
+phase_field/phasefields/phasefield_exponential.cc: this->g_c(type, _not_ghost))) {
+phase_field/phasefields/phasefield_exponential.cc: dam = Matrix<Real, dim, dim>::Identity() * gc * this->l0;
+phase_field/phasefields/phasefield_exponential.cc: this->phi(el_type, ghost_type), this->phi.previous(el_type, ghost_type),
+phase_field/phasefields/phasefield_exponential.cc: make_view(this->strain(el_type, ghost_type), dim, dim));
+phase_field/phasefields/phasefield_exponential.cc: if (this->isotropic) {
+phase_field/phasefields/phasefield_exponential.cc: zip(this->phi(el_type, ghost_type),
+phase_field/phasefields/phasefield_exponential.cc: this->driving_force(el_type, ghost_type),
+phase_field/phasefields/phasefield_exponential.cc: this->damage_energy_density(el_type, ghost_type),
+phase_field/phasefields/phasefield_exponential.cc: this->damage_on_qpoints(el_type, _not_ghost),
+phase_field/phasefields/phasefield_exponential.cc: make_view(this->driving_energy(el_type, ghost_type), dim),
+phase_field/phasefields/phasefield_exponential.cc: make_view(this->damage_energy(el_type, ghost_type), dim, dim),
+phase_field/phasefields/phasefield_exponential.cc: make_view(this->gradd(el_type, ghost_type), dim),
+phase_field/phasefields/phasefield_exponential.cc: this->g_c(el_type, ghost_type))) {
+phase_field/phasefields/phasefield_exponential.cc: zip(this->dissipated_energy(el_type, _not_ghost),
+phase_field/phasefields/phasefield_exponential.cc: this->damage_on_qpoints(el_type, _not_ghost),
+phase_field/phasefields/phasefield_exponential.cc: make_view<dim>(this->gradd(el_type, _not_ghost)),
+phase_field/phasefields/phasefield_exponential.cc: this->g_c(el_type, _not_ghost))) {
+phase_field/phasefields/phasefield_exponential.cc: this->computeDissipatedEnergyOnQuad(damage, grad_d, dis_energy, g_c);
+phase_field/phasefields/phasefield_exponential.cc: auto && fem = this->getFEEngine();
+phase_field/phasefields/phasefield_exponential.cc: auto gradd_it = make_view<dim>(this->gradd(type)).begin() + quad;
+phase_field/phasefields/phasefield_exponential.cc: auto damage_it = this->damage_on_qpoints(type).begin() + quad;
+phase_field/phasefields/phasefield_exponential.cc: auto g_c_it = this->g_c(type).begin() + quad;
+phase_field/phasefields/phasefield_exponential.cc: this->computeDissipatedEnergyOnQuad(*damage_it, *gradd_it, *edis_quad,
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: edis += 0.5 * g_c_quad * this->l0 * grad_d[i] * grad_d[i];
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: edis += g_c_quad * dam * dam / (2. * this->l0);
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: dam_energy_quad = 2.0 * phi_quad + g_c_quad / this->l0;
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: Real kpa = this->lambda + 2. * this->mu / Real(dev_dim);
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: this->mu * strain_dev.doubleDot(strain_dev);
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: phi_quad = 0.5 * this->lambda * trace * trace +
+phase_field/phasefields/phasefield_exponential_inline_impl.hh: this->mu * strain_quad.doubleDot(strain_quad);
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // this->registerParam("ft", this->ft, 0., _pat_parsable, "Tensile strength");
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // const Mesh & mesh = this->material.getModel().getFEEngine().getMesh();
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // this->material.getModel().getFEEngine().getNbQuadraturePoints(*it, gt);
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // this->material.getElementFilter(*it, gt);
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // this->material.getModel().getFEEngine().integrateOnQuadraturePoints(ones,
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // const Mesh & mesh = this->material.getModel().getFEEngine().getMesh();
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // this->material.getStress(*it, ghost_type).begin(spatial_dimension,
+solid_mechanics/materials/weight_functions/stress_based_weight_function.cc: // (*eigenvalues)(i) = std::max(*cl / this->R, (*eigenvalues)(i));
+contact_mechanics/contact_detector.cc: this->spatial_dimension = mesh.getSpatialDimension();
+contact_mechanics/contact_detector.cc: this->positions.copy(positions);
+contact_mechanics/contact_detector.cc: this->parseSection(section);
+contact_mechanics/contact_detector.cc: this->detection_type = _implicit;
+contact_mechanics/contact_detector.cc: this->detection_type = _explicit;
+contact_mechanics/contact_detector.cc: this->projection_tolerance =
+contact_mechanics/contact_detector.cc: this->max_iterations = section.getParameterValue<Int>("max_iterations");
+contact_mechanics/contact_detector.cc: this->extension_tolerance =
+contact_mechanics/contact_detector.cc: this->mesh.fillNodesToElements(surface_dimension);
+contact_mechanics/contact_detector.cc: this->computeMaximalDetectionDistance();
+contact_mechanics/contact_detector.cc: auto && [bbox, master_grid] = this->globalSearch();
+contact_mechanics/contact_detector.cc: this->localSearch(bbox, *master_grid);
+contact_mechanics/contact_detector.cc: this->createContactElements(elements, gaps, normals, tangents, projections);
+contact_mechanics/contact_detector.cc: this->constructBoundingBox(bbox_master, master_list);
+contact_mechanics/contact_detector.cc: this->constructBoundingBox(bbox_slave, slave_list);
+contact_mechanics/contact_detector.cc: this->computeCellSpacing(spacing);
+contact_mechanics/contact_detector.cc: this->constructGrid(*master_grid, bbox_intersection, master_list);
+contact_mechanics/contact_detector.cc: // this->constructGrid(slave_grid, bbox_intersection, slave_list);
+contact_mechanics/contact_detector.cc: auto && elements = this->mesh.getAssociatedElements(slave_node);
+contact_mechanics/contact_detector.cc: const auto & connectivity = this->mesh.getConnectivity(elem);
+contact_mechanics/contact_detector.cc: auto && elements = this->mesh.getAssociatedElements(master_node);
+contact_mechanics/contact_detector.cc: alpha, this->max_iterations, this->projection_tolerance,
+contact_mechanics/contact_detector.cc: this->extension_tolerance);
+contact_mechanics/resolution.cc: this->initialize();
+contact_mechanics/resolution.cc: this->assembleInternalForces();
+contact_mechanics/surface_selector.cc: this->mesh.registerEventHandler(*this, _ehp_lowest);
+contact_mechanics/surface_selector.cc: this->mesh.registerEventHandler(*this, _ehp_lowest);
+contact_mechanics/surface_selector.cc: auto surface_dimension = this->mesh.getSpatialDimension() - 1;
+contact_mechanics/contact_mechanics_model.cc: this->initDOFManager(dof_manager);
+contact_mechanics/contact_mechanics_model.cc: this->registerFEEngineObject<MyFEEngineType>("ContactMechanicsModel", mesh,
+contact_mechanics/contact_mechanics_model.cc: this->mesh.registerDumper<DumperParaview>("contact_mechanics", id, true);
+contact_mechanics/contact_mechanics_model.cc: this->mesh.addDumpMeshToDumper("contact_mechanics", mesh,
+contact_mechanics/contact_mechanics_model.cc: this->registerDataAccessor(*this);
+contact_mechanics/contact_mechanics_model.cc: this->detector =
+contact_mechanics/contact_mechanics_model.cc: std::make_unique<ContactDetector>(this->mesh, id + ":contact_detector");
+contact_mechanics/contact_mechanics_model.cc: if (not this->parser.getLastParsedFile().empty()) {
+contact_mechanics/contact_mechanics_model.cc: this->instantiateResolutions();
+contact_mechanics/contact_mechanics_model.cc: this->initResolutions();
+contact_mechanics/contact_mechanics_model.cc: this->initBC(*this, *displacement, *displacement_increment, *external_force);
+contact_mechanics/contact_mechanics_model.cc: std::tie(model_section, is_empty) = this->getParserSection();
+contact_mechanics/contact_mechanics_model.cc: this->registerNewResolution(section);
+contact_mechanics/contact_mechanics_model.cc: this->parser.getSubSections(ParserType::_contact_resolution);
+contact_mechanics/contact_mechanics_model.cc: this->registerNewResolution(section);
+contact_mechanics/contact_mechanics_model.cc: Resolution & res = this->registerNewResolution(res_name, res_type, opt_param);
+contact_mechanics/contact_mechanics_model.cc: sstr_res << this->id << ":" << res_count << ":" << res_type;
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->displacement, spatial_dimension, "displacement");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->displacement_increment, spatial_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->internal_force, spatial_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->external_force, spatial_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->normal_force, spatial_dimension, "normal_force");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->tangential_force, spatial_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->gaps, 1, "gaps");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->nodal_area, 1, "areas");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->blocked_dofs, 1, "blocked_dofs");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->contact_state, 1, "contact_state");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->previous_master_elements, 1,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->normals, spatial_dimension, "normals");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->tangents, surface_dimension * spatial_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->projections, surface_dimension, "projections");
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->previous_projections, surface_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->previous_tangents,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->tangential_tractions, surface_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->allocNodalField(this->previous_tangential_tractions, surface_dimension,
+contact_mechanics/contact_mechanics_model.cc: this->assembleInternalForces();
+contact_mechanics/contact_mechanics_model.cc: this->getDOFManager().assembleToResidual("displacement",
+contact_mechanics/contact_mechanics_model.cc: *this->internal_force, 1);
+contact_mechanics/contact_mechanics_model.cc: this->internal_force->clear();
+contact_mechanics/contact_mechanics_model.cc: this->normal_force->clear();
+contact_mechanics/contact_mechanics_model.cc: this->tangential_force->clear();
+contact_mechanics/contact_mechanics_model.cc: this->savePreviousState();
+contact_mechanics/contact_mechanics_model.cc: this->detector->search(contact_elements, *gaps, *normals, *tangents,
+contact_mechanics/contact_mechanics_model.cc: this->computeNodalAreas();
+contact_mechanics/contact_mechanics_model.cc: this->getDOFManager().assembleElementalArrayLocalArray(
+contact_mechanics/contact_mechanics_model.cc: this->external_force->clear();
+contact_mechanics/contact_mechanics_model.cc: this->assembleStiffnessMatrix();
+contact_mechanics/contact_mechanics_model.cc: if (!this->getDOFManager().hasMatrix("K")) {
+contact_mechanics/contact_mechanics_model.cc: this->getDOFManager().getNewMatrix("K", getMatrixType("K"));
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["contact_force"] = this->internal_force.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["normal_force"] = this->normal_force.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["tangential_force"] = this->tangential_force.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["normals"] = this->normals.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["tangents"] = this->tangents.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["gaps"] = this->gaps.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["areas"] = this->nodal_area.get();
+contact_mechanics/contact_mechanics_model.cc: real_nodal_fields["tangential_traction"] = this->tangential_tractions.get();
+contact_mechanics/contact_mechanics_model.cc: field = this->mesh.createNodalField(real_nodal_fields[field_name],
+contact_mechanics/contact_mechanics_model.cc: this->mesh.createNodalField(real_nodal_fields[field_name], group_name);
+contact_mechanics/contact_mechanics_model.cc: field = mesh.createNodalField(this->contact_state.get(), group_name);
+contact_mechanics/resolutions/resolution_penalty_quadratic.cc: this->initialize();
+contact_mechanics/resolutions/resolution_penalty.cc: this->initialize();
+contact_mechanics/resolutions/resolution_penalty.cc: this->registerParam("epsilon_n", epsilon_n, Real(0.),
+contact_mechanics/resolutions/resolution_penalty.cc: this->registerParam("epsilon_t", epsilon_t, Real(0.),
+contact_mechanics/resolutions/resolution_penalty.cc: this->computeTangentialTraction(element, covariant_basis,
+contact_mechanics/resolutions/resolution_penalty.cc: this->computeTrialTangentialTraction(element, covariant_basis,
+contact_mechanics/contact_detector_inline_impl.hh: auto position_it = make_view(this->positions, spatial_dimension).begin();
+contact_mechanics/contact_detector_inline_impl.hh: auto && pos = make_view(this->positions, spatial_dimension).begin()[node];
+contact_mechanics/contact_detector_inline_impl.hh: auto & master_nodes = this->surface_selector->getMasterList();
+contact_mechanics/contact_detector_inline_impl.hh: this->mesh.getAssociatedElements(master, elements);
+contact_mechanics/contact_detector_inline_impl.hh: this->coordinatesOfElement(element, elem_coords);
+contact_mechanics/contact_detector_inline_impl.hh: this->min_dd = min_elem_size;
+contact_mechanics/contact_detector_inline_impl.hh: this->max_dd = max_elem_size;
+contact_mechanics/contact_detector_inline_impl.hh: this->max_bb = max_elem_size;
+contact_mechanics/contact_detector_inline_impl.hh: auto && master_conn = this->mesh.getConnectivity(master);
+contact_mechanics/contact_detector_inline_impl.hh: this->vectorsAlongElement(element, vectors);
+contact_mechanics/contact_detector_inline_impl.hh: switch (this->spatial_dimension) {
+contact_mechanics/contact_detector_inline_impl.hh: this->coordinatesOfElement(el, coords);
+contact_mechanics/contact_detector_inline_impl.hh: auto && slave_elements = this->mesh.getAssociatedElements(slave_node);
+contact_mechanics/contact_detector_inline_impl.hh: auto && connectivity = this->mesh.getConnectivity(element);
diff --git a/src/model/model.cc b/src/model/model.cc
index 89f5b9861..47527b8ba 100644
--- a/src/model/model.cc
+++ b/src/model/model.cc
@@ -1,339 +1,337 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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,
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->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<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, Int step) {
mesh.dump(dumper_name, 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(Int step) {
auto default_dumper = mesh.getDefaultDumperName();
this->dump(default_dumper, 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 2baaa4ec1..9a8629028 100644
--- a/src/model/model.hh
+++ b/src/model/model.hh
@@ -1,371 +1,375 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int dim = _all_dimensions,
const ID & id = "model");
~Model() override;
+ /* ------------------------------------------------------------------------ */
+ Model(const Model & /*other*/) = delete;
+ Model(Model && /*other*/) = delete;
+ Model & operator=(const Model & /*other*/) = delete;
+ Model & operator=(Model && /*other*/) = delete;
+ /* ------------------------------------------------------------------------ */
+
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
+#ifdef AKANTU_DIFFUSION
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;
+ getDefaultSolverID(const AnalysisMethod & /*method*/) {
+ return {"none", TimeStepSolverType::_not_defined};
+ }
- virtual void initModel(){};
+ virtual void initModel() {}
virtual void initFEEngineBoundary();
/// function to print the containt of the class
- void printself(std::ostream & /*stream*/,
- int /*indent*/ = 0) const override{};
+ 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) {
+ virtual void
+ updateDataForNonLocalCriterion(ElementTypeMapReal & /*criterion*/) {
AKANTU_TO_IMPLEMENT();
}
protected:
template <typename T>
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;
+ [[nodiscard]] 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,
- Int spatial_dimension);
+ inline void registerFEEngineObject(const ID & name, Mesh & mesh,
+ Int spatial_dimension = _all_dimensions,
+ bool do_not_precompute = false);
+
/// unregister a fem object associated with name
- inline void unRegisterFEEngineObject(const std::string & name);
+ inline void unRegisterFEEngineObject(const ID & 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;
+ inline FEEngineClass & getFEEngineClass(const ID & name = "") const;
/// return the fem boundary object associated with a provided name
template <typename FEEngineClass>
- inline FEEngineClass & getFEEngineClassBoundary(std::string name = "");
+ inline FEEngineClass & getFEEngineClassBoundary(const ID & 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, Int);
/* ------------------------------------------------------------------------ */
/* Pack and unpack hexlper functions */
/* ------------------------------------------------------------------------ */
public:
- inline Int getNbIntegrationPoints(const Array<Element> & elements,
- const ID & fem_id = ID()) const;
+ [[nodiscard]] 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,
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>
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*/, 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, Int step);
virtual void dump(const std::string & dumper_name, Real time, Int step);
/* ------------------------------------------------------------------------ */
virtual void dump();
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;
+ const Model & /*this*/);
/// analysis method check the list in akantu::AnalysisMethod
AnalysisMethod method;
/// Mesh
Mesh & mesh;
/// Spatial dimension of the problem
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/cohesive_contact_solvercallback.hh b/src/model/model_couplers/cohesive_contact_solvercallback.hh
index 61ae09a19..584534f4f 100644
--- a/src/model/model_couplers/cohesive_contact_solvercallback.hh
+++ b/src/model/model_couplers/cohesive_contact_solvercallback.hh
@@ -1,78 +1,78 @@
/**
* Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "mesh_iterators.hh"
#include "non_linear_solver.hh"
#include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_COHESIVE_CONTACT_SOLVERCALLBACK_HH__
-#define __AKANTU_COHESIVE_CONTACT_SOLVERCALLBACK_HH__
+#ifndef AKANTU_COHESIVE_CONTACT_SOLVERCALLBACK_HH_
+#define AKANTU_COHESIVE_CONTACT_SOLVERCALLBACK_HH_
namespace akantu {
class CohesiveContactSolverCallback : public SolverCallback {
public:
CohesiveContactSolverCallback(SolidMechanicsModelCohesive & /*solid*/,
ContactMechanicsModel & /*contact*/,
AnalysisMethod & /*method*/);
public:
/// implementation of SolverCallback::assembleMatrix
void assembleMatrix(const ID & /*matrix_id*/) override;
/// implementation of SolverCallback::assembleResidual
void assembleResidual() override;
/// implementation of SolverCallback::assembleLumpedMatrix
void assembleLumpedMatrix(const ID & /*matrix_id*/) override;
/// implementation of SolverCallback::getMatrixType
MatrixType getMatrixType(const ID & /*unused*/) const override;
/// implementation of SolverCallback::predictor
void predictor() override;
/// implementation of SolverCallback::corrector
void corrector() override;
/// implementation of SolverCallback::beforeSolveStep
void beforeSolveStep() override;
/// implementation of SolverCallback::afterSolveStep
void afterSolveStep(bool converged = true) override;
private:
/// model for the solid mechanics part of the coupling
SolidMechanicsModelCohesive & solid;
/// model for the contact resoluion of the coupling
ContactMechanicsModel & contact;
/// Method of resolution for the coupling solver
AnalysisMethod & method;
};
} // namespace akantu
#endif
diff --git a/src/model/model_couplers/coupler_solid_cohesive_contact.cc b/src/model/model_couplers/coupler_solid_cohesive_contact.cc
index 1614da172..88a710eca 100644
--- a/src/model/model_couplers/coupler_solid_cohesive_contact.cc
+++ b/src/model/model_couplers/coupler_solid_cohesive_contact.cc
@@ -1,64 +1,65 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
+#include "element_synchronizer.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
template <>
CouplerSolidContactTemplate<SolidMechanicsModelCohesive>::
CouplerSolidContactTemplate(Mesh & mesh, Int dim, const ID & id,
- std::shared_ptr<DOFManager> dof_manager)
+ const 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_cohesive_contact.hh b/src/model/model_couplers/coupler_solid_cohesive_contact.hh
index 138918537..629a68d07 100644
--- a/src/model/model_couplers/coupler_solid_cohesive_contact.hh
+++ b/src/model/model_couplers/coupler_solid_cohesive_contact.hh
@@ -1,39 +1,39 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_COUPLER_SOLID_COHESIVE_CONTACT_HH__
-#define __AKANTU_COUPLER_SOLID_COHESIVE_CONTACT_HH__
+#ifndef AKANTU_COUPLER_SOLID_COHESIVE_CONTACT_HH_
+#define AKANTU_COUPLER_SOLID_COHESIVE_CONTACT_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
using CouplerSolidCohesiveContact =
CouplerSolidContactTemplate<SolidMechanicsModelCohesive>;
} // namespace akantu
#endif /* __COUPLER_SOLID_CONTACT_HH__ */
diff --git a/src/model/model_couplers/coupler_solid_contact.cc b/src/model/model_couplers/coupler_solid_contact.cc
index 4b48ccd8f..a7924fab8 100644
--- a/src/model/model_couplers/coupler_solid_contact.cc
+++ b/src/model/model_couplers/coupler_solid_contact.cc
@@ -1,59 +1,59 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int dim, const ID & id,
- std::shared_ptr<DOFManager> dof_manager)
+ const 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 9c4831589..926e1cbce 100644
--- a/src/model/model_couplers/coupler_solid_contact.hh
+++ b/src/model/model_couplers/coupler_solid_contact.hh
@@ -1,260 +1,283 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#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<Idx> {
static_assert(
std::is_base_of<SolidMechanicsModel, SolidMechanicsModelType>::value,
"SolidMechanicsModelType should be derived from SolidMechanicsModel");
/* ------------------------------------------------------------------------ */
/* Constructor/Destructor */
/* ------------------------------------------------------------------------ */
public:
CouplerSolidContactTemplate(
Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "coupler_solid_contact",
- std::shared_ptr<DOFManager> dof_manager = nullptr);
-
- ~CouplerSolidContactTemplate() override;
+ const std::shared_ptr<DOFManager> & dof_manager = nullptr);
/* ------------------------------------------------------------------------ */
/* 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(FunctorType && func) {
solid->applyBC(std::forward<decltype(func)>(func));
}
template <class FunctorType>
inline void applyBC(FunctorType && func, const std::string & group_name) {
solid->applyBC(std::forward<decltype(func)>(func), group_name);
}
template <class FunctorType>
inline void applyBC(FunctorType && func, const ElementGroup & element_group) {
solid->applyBC(std::forward<decltype(func)>(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; }
+ [[nodiscard]] bool canSplitResidual() const override { return true; }
/// get the type of matrix needed
- MatrixType getMatrixType(const ID & matrix_id) const override;
+ [[nodiscard]] 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;
+ [[nodiscard]] TimeStepSolverType getDefaultSolverType() const override;
/* ------------------------------------------------------------------------ */
- ModelSolverOptions
+ [[nodiscard]] ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) const override;
public:
bool isDefaultSolverExplicit() { return method == _explicit_lumped_mass; }
/* ------------------------------------------------------------------------ */
public:
// DataAccessor<Element>
- Int getNbData(const Array<Element> & /*elements*/,
- const SynchronizationTag & /*tag*/) const override {
+ [[nodiscard]] 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
- Int getNbData(const Array<Idx> & /*nodes*/,
- const SynchronizationTag & /*tag*/) const override {
+ [[nodiscard]] Int
+ getNbData(const Array<Idx> & /*nodes*/,
+ const SynchronizationTag & /*tag*/) const override {
return 0;
}
void packData(CommunicationBuffer & /*buffer*/, const Array<Idx> & /*nodes*/,
const SynchronizationTag & /*tag*/) const override {}
void unpackData(CommunicationBuffer & /*buffer*/,
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 &)
+ [[nodiscard]] Real getStableTimeStep() const {
+ return solid->getStableTimeStep();
+ }
+
+ [[nodiscard]] Array<Real> & getDisplacement() {
+ return solid->getDisplacement();
+ }
+ [[nodiscard]] Array<Real> & getVelocity() { return solid->getVelocity(); }
+ [[nodiscard]] Array<Real> & getAcceleration() {
+ return solid->getAcceleration();
+ }
+ [[nodiscard]] Array<Real> & getExternalForce() {
+ return solid->getExternalForce();
+ }
+ [[nodiscard]] const Array<Real> & getMass() { return solid->getMass(); }
+ [[nodiscard]] Array<Real> & getContactForce() {
+ return solid->getInternalForce();
+ }
+
+ [[nodiscard]] ContactDetector & getContactDetector() {
+ return contact->getContactDetector();
+ }
+
/* ------------------------------------------------------------------------ */
/* 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>
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,
Int spatial_dimension, ElementKind kind) override;
void dump(const std::string & dumper_name) 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(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;
+ Idx 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 6f54f9a2a..f4f365d93 100644
--- a/src/model/model_couplers/coupler_solid_contact_tmpl.hh
+++ b/src/model/model_couplers/coupler_solid_contact_tmpl.hh
@@ -1,383 +1,378 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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>::createNodalFieldInt(
const std::string & field_name, const std::string & group_name,
bool padding_flag) {
std::shared_ptr<dumpers::Field> field;
field = contact->createNodalFieldInt(field_name, group_name, padding_flag);
if (not field) {
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, Int step) {
solid->onDump();
Model::dump(dumper_name, step);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(
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(Int step) {
solid->onDump();
Model::dump(step);
}
/* -------------------------------------------------------------------------- */
template <class SolidMechanicsModelType>
void CouplerSolidContactTemplate<SolidMechanicsModelType>::dump(Real time,
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 3c77ea0a6..6a259cfd8 100644
--- a/src/model/model_couplers/coupler_solid_phasefield.cc
+++ b/src/model/model_couplers/coupler_solid_phasefield.cc
@@ -1,567 +1,532 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int dim,
const ID & id,
const ModelType model_type)
: Model(mesh, model_type, dim, id) {
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");
+ solid = std::make_unique<SolidMechanicsModel>(mesh, Model::spatial_dimension,
+ "solid_mechanics_model");
+ phase = std::make_unique<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);
}
}
/* -------------------------------------------------------------------------- */
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(GhostType ghost_type) {
-
- AKANTU_DEBUG_IN();
-
auto & fem = phase->getFEEngine();
auto & mesh = phase->getMesh();
- auto nb_materials = solid->getNbMaterials();
- auto nb_phasefields = phase->getNbPhaseFields();
+ auto nb_materials = solid->getNbConstitutiveLaws();
+ auto nb_phasefields = phase->getNbConstitutiveLaws();
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);
+ auto & material = solid->getConstitutiveLaw(index);
for (auto index2 : arange(nb_phasefields)) {
- auto & phasefield = phase->getPhaseField(index2);
+ auto & phasefield = phase->getConstitutiveLaw(index2);
if (phasefield.getName() == material.getName()) {
-
- switch (spatial_dimension) {
- case 1: {
- auto & mat = static_cast<MaterialDamage<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<MaterialDamage<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<MaterialDamage<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;
- }
+ tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) {
+ constexpr auto && dim_ = aka::decay_v<decltype(_)>;
+ auto & mat = static_cast<MaterialPhaseField<dim_> &>(material);
+ auto & damage = mat.getDamage();
+ for (const auto & type :
+ mesh.elementTypes(this->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);
+ }
+ },
+ this->spatial_dimension);
}
}
}
-
- AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------- */
void CouplerSolidPhaseField::computeStrainOnQuadPoints(GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto & gradu_internal =
solid->flattenInternal("grad_u", _ek_regular, ghost_type);
auto & mesh = solid->getMesh();
auto & fem = solid->getFEEngine();
ElementTypeMapArray<Real> strain_tmp("temporary strain on quads");
- strain_tmp.initialize(
- fem, _nb_component = spatial_dimension * spatial_dimension,
- _spatial_dimension = spatial_dimension, _ghost_type = ghost_type);
+ strain_tmp.initialize(fem,
+ _nb_component = spatial_dimension * spatial_dimension,
+ _spatial_dimension = spatial_dimension,
+ _ghost_type = ghost_type, _with_nb_element = true);
for (const auto & type : mesh.elementTypes(spatial_dimension, ghost_type)) {
auto & strain_vect = strain_tmp(type, ghost_type);
const auto & gradu_vect = gradu_internal(type, ghost_type);
- for (auto && values :
+ for (auto && [grad_u, strain] :
zip(make_view(gradu_vect, spatial_dimension, spatial_dimension),
make_view(strain_vect, spatial_dimension, spatial_dimension))) {
- const auto & grad_u = std::get<0>(values);
- auto & strain = std::get<1>(values);
- // strain = (grad_u + grad_u.transpose()) / 2.;
- strain = grad_u;
+ strain = (grad_u + grad_u.transpose()) / 2.;
}
}
- phase->inflateInternal("grad_u", strain_tmp, _ek_regular, ghost_type);
- phase->computeStrain(ghost_type);
+ phase->inflateInternal("strain", strain_tmp, ghost_type, _ek_regular);
AKANTU_DEBUG_OUT();
}
/* ------------------------------------------------------------------------- */
void CouplerSolidPhaseField::solve(const ID & solid_solver_id,
const ID & phase_solver_id) {
solid->solveStep(solid_solver_id);
solid->synchronize(SynchronizationTag::_smm_gradu);
AKANTU_DEBUG_INFO("exchange strain for local elements");
this->computeStrainOnQuadPoints(_not_ghost);
AKANTU_DEBUG_INFO("exchange strain for ghost elements");
this->computeStrainOnQuadPoints(_ghost);
phase->solveStep(phase_solver_id);
phase->synchronize(SynchronizationTag::_pfm_damage);
AKANTU_DEBUG_INFO("exchange damage for local elements");
this->computeDamageOnQuadPoints(_not_ghost);
AKANTU_DEBUG_INFO("exchange damage for ghost elements");
this->computeDamageOnQuadPoints(_ghost);
solid->assembleInternalForces();
}
/* ------------------------------------------------------------------------- */
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();
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 (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 (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, 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, Int step) {
solid->onDump();
mesh.dump(dumper_name, step);
}
/* ----------------------------------------------------------------------- */
void CouplerSolidPhaseField::dump(const std::string & dumper_name, Real time,
Int step) {
solid->onDump();
mesh.dump(dumper_name, time, step);
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::dump() {
solid->onDump();
mesh.dump();
}
/* -------------------------------------------------------------------------- */
void CouplerSolidPhaseField::dump(Int step) {
solid->onDump();
mesh.dump(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 20894e7d9..c1062ed0b 100644
--- a/src/model/model_couplers/coupler_solid_phasefield.hh
+++ b/src/model/model_couplers/coupler_solid_phasefield.hh
@@ -1,247 +1,246 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "phasefield.hh"
#include "phase_field_model.hh"
+#include "phasefield.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__
+#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<Idx>,
public BoundaryCondition<CouplerSolidPhaseField> {
/* ------------------------------------------------------------------------ */
/* Constructor/Destructors */
/* ------------------------------------------------------------------------ */
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
public:
CouplerSolidPhaseField(
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(GhostType ghost_type);
/// computes strain on quadrature points for phasefield model from
/// displacement gradient from solid mechanics model
void computeStrainOnQuadPoints(GhostType ghost_type);
/// solve the coupled model
void solve(const ID & solid_solver_id = "", const ID & phase_solver_id = "");
private:
/// 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; }
/* ------------------------------------------------------------------------ */
/* 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,
Int spatial_dimension, ElementKind kind) override;
void dump(const std::string & dumper_name) 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(Int step) override;
void dump(Real time, Int step) override;
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
/// solid mechanics model
- SolidMechanicsModel * solid{nullptr};
+ std::unique_ptr<SolidMechanicsModel> solid;
/// phasefield model
- PhaseFieldModel * phase{nullptr};
+ std::unique_ptr<PhaseFieldModel> phase;
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__ */
+#endif /* AKANTU_COUPLER_SOLID_PHASEFIELD_HH_ */
diff --git a/src/model/model_inline_impl.hh b/src/model/model_inline_impl.hh
index 618fb8d4d..c464e4cc7 100644
--- a/src/model/model_inline_impl.hh
+++ b/src/model/model_inline_impl.hh
@@ -1,164 +1,163 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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;
- }
+inline FEEngineClass & Model::getFEEngineClassBoundary(const ID & name) {
+ auto tmp_name = name.empty() ? default_fem : name;
+
+ auto has_fem_boundary = hasFEEngineBoundary(tmp_name);
+ auto boundary_name = tmp_name + ":boundary";
- auto it_boun = fems_boundary.find(name);
+ if (not has_fem_boundary) {
+ AKANTU_DEBUG_INFO("Creating FEEngine boundary " << tmp_name);
- if (it_boun == fems_boundary.end()) {
- AKANTU_DEBUG_INFO("Creating FEEngine boundary " << name);
+ auto & fe_engine = getFEEngine(tmp_name);
- auto it = fems.find(name);
- if (it == fems.end()) {
- AKANTU_EXCEPTION("The FEEngine " << name << " is not registered");
- }
+ auto spatial_dimension = fe_engine.getElementDimension();
+ registerFEEngineObject<FEEngineClass>(boundary_name, fe_engine.getMesh(),
+ spatial_dimension - 1);
- auto spatial_dimension = it->second->getElementDimension();
- fems_boundary[name] = std::make_unique<FEEngineClass>(
- it->second->getMesh(), spatial_dimension - 1,
- id + ":fem_boundary:" + name);
+ auto & fem_boundary = getFEEngineClass<FEEngineClass>(boundary_name);
+ fem_boundary.computeNormalsOnIntegrationPoints(_not_ghost);
+ fem_boundary.computeNormalsOnIntegrationPoints(_ghost);
+ return fem_boundary;
}
- return aka::as_type<FEEngineClass>(*fems_boundary[name]);
+ return getFEEngineClass<FEEngineClass>(boundary_name);
}
/* -------------------------------------------------------------------------- */
template <typename FEEngineClass>
-inline FEEngineClass & Model::getFEEngineClass(std::string name) const {
- if (name.empty()) {
- name = default_fem;
- }
+inline FEEngineClass & Model::getFEEngineClass(const ID & name) const {
+ auto tmp_name = name.empty() ? default_fem : name;
- auto it = fems.find(name);
+ auto it = fems.find(tmp_name);
if (it == fems.end()) {
- AKANTU_EXCEPTION("The FEEngine " << name << " is not registered");
+ AKANTU_EXCEPTION("The FEEngine " << tmp_name << " is not registered");
}
return aka::as_type<FEEngineClass>(*(it->second));
}
/* -------------------------------------------------------------------------- */
-inline void Model::unRegisterFEEngineObject(const std::string & name) {
+inline void Model::unRegisterFEEngineObject(const ID & 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;
+ default_fem = fems.begin()->first;
}
}
/* -------------------------------------------------------------------------- */
template <typename FEEngineClass>
-inline void Model::registerFEEngineObject(const std::string & name, Mesh & mesh,
- Int spatial_dimension) {
+inline void Model::registerFEEngineObject(const ID & name, Mesh & mesh,
+ Int spatial_dimension,
+ bool do_not_precompute) {
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);
+ fems[name] = std::make_unique<FEEngineClass>(
+ mesh, spatial_dimension, id + ":fem:" + name, do_not_precompute);
}
/* -------------------------------------------------------------------------- */
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()) {
+ auto it = fems.find(tmp_name + ":boundary");
+ if (it == fems.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());
+ auto it = fems.find(tmp_name + ":boundary");
+ return (it != fems.end());
}
/* -------------------------------------------------------------------------- */
template <typename T>
-void Model::allocNodalField(std::unique_ptr<Array<T>> & array,
- Int nb_component, const ID & name) const {
+void Model::allocNodalField(std::unique_ptr<Array<T>> & array, Int nb_component,
+ const ID & name) const {
if (array) {
return;
}
auto nb_nodes = mesh.getNbNodes();
array =
std::make_unique<Array<T>>(nb_nodes, nb_component, T(), id + ":" + name);
}
/* -------------------------------------------------------------------------- */
inline Int Model::getNbIntegrationPoints(const Array<Element> & elements,
- const ID & fem_id) const {
+ const ID & fem_id) const {
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/model_options.hh b/src/model/model_options.hh
index e47a425b5..c99cb4b0e 100644
--- a/src/model/model_options.hh
+++ b/src/model/model_options.hh
@@ -1,194 +1,195 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MODEL_OPTIONS_HH_
#define AKANTU_MODEL_OPTIONS_HH_
namespace akantu {
namespace {
DECLARE_NAMED_ARGUMENT(analysis_method);
}
-struct ModelOptions {
+class ModelOptions {
+public:
explicit ModelOptions(AnalysisMethod analysis_method = _static)
: analysis_method(analysis_method) {}
template <typename... pack>
ModelOptions(use_named_args_t /*unused*/, pack &&... _pack)
: ModelOptions(OPTIONAL_NAMED_ARG(analysis_method, _static)) {}
virtual ~ModelOptions() = default;
AnalysisMethod analysis_method;
};
#ifdef AKANTU_SOLID_MECHANICS
/* -------------------------------------------------------------------------- */
struct SolidMechanicsModelOptions : public ModelOptions {
explicit SolidMechanicsModelOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass)
: ModelOptions(analysis_method) {}
template <typename... pack>
SolidMechanicsModelOptions(use_named_args_t /*unused*/, pack &&... _pack)
: SolidMechanicsModelOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {}
};
#endif
/* -------------------------------------------------------------------------- */
#ifdef AKANTU_COHESIVE_ELEMENT
namespace {
DECLARE_NAMED_ARGUMENT(is_extrinsic);
}
/* -------------------------------------------------------------------------- */
struct SolidMechanicsModelCohesiveOptions : public SolidMechanicsModelOptions {
SolidMechanicsModelCohesiveOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass,
bool extrinsic = false)
: SolidMechanicsModelOptions(analysis_method), is_extrinsic(extrinsic) {}
template <typename... pack>
SolidMechanicsModelCohesiveOptions(use_named_args_t /*unused*/,
pack &&... _pack)
: SolidMechanicsModelCohesiveOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass),
OPTIONAL_NAMED_ARG(is_extrinsic, false)) {}
bool is_extrinsic{false};
};
#endif
-#ifdef AKANTU_HEAT_TRANSFER
+#ifdef AKANTU_DIFFUSION
/* -------------------------------------------------------------------------- */
struct HeatTransferModelOptions : public ModelOptions {
explicit HeatTransferModelOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass)
: ModelOptions(analysis_method) {}
template <typename... pack>
HeatTransferModelOptions(use_named_args_t /*unused*/, pack &&... _pack)
: HeatTransferModelOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {}
};
#endif
#ifdef AKANTU_PHASE_FIELD
/* -------------------------------------------------------------------------- */
struct PhaseFieldModelOptions : public ModelOptions {
explicit PhaseFieldModelOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass)
: ModelOptions(analysis_method) {}
template <typename... pack>
PhaseFieldModelOptions(use_named_args_t /*unused*/, pack &&... _pack)
: PhaseFieldModelOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {}
};
#endif
/* -------------------------------------------------------------------------- */
#ifdef AKANTU_EMBEDDED
namespace {
DECLARE_NAMED_ARGUMENT(init_intersections);
}
/* -------------------------------------------------------------------------- */
struct EmbeddedInterfaceModelOptions : SolidMechanicsModelOptions {
/**
* @brief Constructor for EmbeddedInterfaceModelOptions
* @param analysis_method see SolidMechanicsModelOptions
* @param init_intersections compute intersections
*/
EmbeddedInterfaceModelOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass,
bool init_intersections = true)
: SolidMechanicsModelOptions(analysis_method),
has_intersections(init_intersections) {}
template <typename... pack>
EmbeddedInterfaceModelOptions(use_named_args_t /*unused*/, pack &&... _pack)
: EmbeddedInterfaceModelOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass),
OPTIONAL_NAMED_ARG(init_intersections, true)) {}
/// Should consider reinforcements
bool has_intersections;
};
#endif
#ifdef AKANTU_CONTACT_MECHANICS
/* -------------------------------------------------------------------------- */
struct ContactMechanicsModelOptions : public ModelOptions {
explicit ContactMechanicsModelOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass)
: ModelOptions(analysis_method) {}
template <typename... pack>
ContactMechanicsModelOptions(use_named_args_t /*unused*/, pack &&... _pack)
: ContactMechanicsModelOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {}
};
#endif
#ifdef AKANTU_MODEL_COUPLERS
/* -------------------------------------------------------------------------- */
struct CouplerSolidContactOptions : public ModelOptions {
explicit CouplerSolidContactOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass)
: ModelOptions(analysis_method) {}
template <typename... pack>
CouplerSolidContactOptions(use_named_args_t /*unused*/, pack &&... _pack)
: CouplerSolidContactOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass)) {}
};
#ifdef AKANTU_COHESIVE_ELEMENT
/* -------------------------------------------------------------------------- */
struct CouplerSolidCohesiveContactOptions : public ModelOptions {
CouplerSolidCohesiveContactOptions(
AnalysisMethod analysis_method = _explicit_lumped_mass,
bool extrinsic = false)
: ModelOptions(analysis_method), is_extrinsic(extrinsic) {}
template <typename... pack>
CouplerSolidCohesiveContactOptions(use_named_args_t /*unused*/,
pack &&... _pack)
: CouplerSolidCohesiveContactOptions(
OPTIONAL_NAMED_ARG(analysis_method, _explicit_lumped_mass),
OPTIONAL_NAMED_ARG(is_extrinsic, false)) {}
bool is_extrinsic{false};
};
#endif
#endif
} // namespace akantu
#endif /* AKANTU_MODEL_OPTIONS_HH_ */
diff --git a/src/model/phase_field/phase_field_element_filter.hh b/src/model/phase_field/phase_field_element_filter.hh
index 6311f0e1d..643b80d18 100644
--- a/src/model/phase_field/phase_field_element_filter.hh
+++ b/src/model/phase_field/phase_field_element_filter.hh
@@ -1,52 +1,49 @@
#include "group_manager.hh"
#include "phase_field_model.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
class PhaseFieldElementFilter : public GroupManager::ClusteringFilter {
public:
PhaseFieldElementFilter(const PhaseFieldModel & model,
const Real max_damage = 1.)
: model(model), is_unbroken(max_damage) {}
bool operator()(const Element & el) const override {
- const Array<Idx> & mat_indexes =
- model.getPhaseFieldByElement(el.type, el.ghost_type);
- const Array<Idx> & mat_loc_num =
- model.getPhaseFieldLocalNumbering(el.type, el.ghost_type);
+ auto mat_id = model.getConstitutiveLawByElement()(el);
+ auto el_index = model.getConstitutiveLawLocalNumbering()(el);
- const auto & mat = model.getPhaseField(mat_indexes(el.element));
+ const auto & mat = model.getPhaseField(mat_id);
- Idx el_index = mat_loc_num(el.element);
Int nb_quad_per_element =
model.getFEEngine("PhaseFieldFEEngine")
.getNbIntegrationPoints(el.type, el.ghost_type);
const Array<Real> & damage_array = mat.getDamage(el.type, el.ghost_type);
AKANTU_DEBUG_ASSERT(nb_quad_per_element * el_index < damage_array.size(),
"This quadrature point is out of range");
const Real * element_damage =
damage_array.data() + nb_quad_per_element * el_index;
- UInt unbroken_quads = std::count_if(
+ auto unbroken_quads = std::count_if(
element_damage, element_damage + nb_quad_per_element, is_unbroken);
return (unbroken_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 PhaseFieldModel & model;
const IsUnbrokenFunctor is_unbroken;
};
-}
+} // namespace akantu
diff --git a/src/model/phase_field/phase_field_model.cc b/src/model/phase_field/phase_field_model.cc
index 57daa499f..cf665d059 100644
--- a/src/model/phase_field/phase_field_model.cc
+++ b/src/model/phase_field/phase_field_model.cc
@@ -1,780 +1,502 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "aka_common.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"
#include <algorithm>
#include <utility>
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
PhaseFieldModel::PhaseFieldModel(Mesh & mesh, Int dim, const ID & id,
std::shared_ptr<DOFManager> dof_manager,
ModelType model_type)
- : Model(mesh, model_type, dim, id),
- phasefield_index("phasefield index", id),
- phasefield_local_numbering("phasefield local numbering", id) {
-
+ : Parent(mesh, model_type, dim, id) {
AKANTU_DEBUG_IN();
this->initDOFManager(std::move(dof_manager));
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->registerDataAccessor(*this);
-
if (this->mesh.isDistributed()) {
auto & synchronizer = this->mesh.getElementSynchronizer();
- this->registerSynchronizer(synchronizer,
- SynchronizationTag::_phasefield_id);
this->registerSynchronizer(synchronizer, SynchronizationTag::_pfm_damage);
this->registerSynchronizer(synchronizer, SynchronizationTag::_for_dump);
}
+ this->parser_type = ParserType::_phasefield;
+
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 = Idx(-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();
- }
+ Parent::initFullImpl(options);
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");
-
- Int 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();
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::assignPhaseFieldToElements(
- const ElementTypeMapArray<Idx> * filter) {
-
- for_each_element(
- mesh,
- [&](auto && element) {
- Int phase_index = (*phasefield_selector)(element);
- AKANTU_DEBUG_ASSERT(
- 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::_phasefield_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));
}
/* -------------------------------------------------------------------------- */
TimeStepSolverType PhaseFieldModel::getDefaultSolverType() const {
return TimeStepSolverType::_static;
}
/* -------------------------------------------------------------------------- */
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::_newton_raphson;
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;
}
/* -------------------------------------------------------------------------- */
-Real PhaseFieldModel::getEnergy() {
+Real PhaseFieldModel::getEnergy(const ID & energy_id) {
AKANTU_DEBUG_IN();
Real energy = 0.;
- for (auto & phasefield : phasefields) {
- energy += phasefield->getEnergy();
- }
+ for_each_constitutive_law([&energy, &energy_id](auto && phase_field) {
+ energy += phase_field.getEnergy(energy_id);
+ });
/// reduction sum over all processors
mesh.getCommunicator().allReduce(energy, SynchronizerOperation::_sum);
AKANTU_DEBUG_OUT();
return energy;
}
/* -------------------------------------------------------------------------- */
-Real PhaseFieldModel::getEnergy(ElementType type, Idx index) {
- AKANTU_DEBUG_IN();
-
- Idx phase_index = this->phasefield_index(type, _not_ghost)(index);
- Idx phase_loc_num = this->phasefield_local_numbering(type, _not_ghost)(index);
- Real energy = this->phasefields[phase_index]->getEnergy(
- Element{type, phase_loc_num, _not_ghost});
-
- AKANTU_DEBUG_OUT();
+Real PhaseFieldModel::getEnergy(const ID & energy_id, const Element & element) {
+ auto pf_element = element;
+ auto phase_index = this->getConstitutiveLawByElement()(element);
+ pf_element.element = this->getConstitutiveLawLocalNumbering()(element);
+ Real energy =
+ this->getConstitutiveLaw(phase_index).getEnergy(energy_id, pf_element);
return energy;
}
/* -------------------------------------------------------------------------- */
-Real PhaseFieldModel::getEnergy(const ID & group_id) {
+Real PhaseFieldModel::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(el);
+ energy += this->getEnergy(energy_id, el);
}
}
/// reduction sum over all processors
mesh.getCommunicator().allReduce(energy, SynchronizerOperation::_sum);
return energy;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::beforeSolveStep() {
- for (auto & phasefield : phasefields) {
- phasefield->beforeSolveStep();
- }
+ for_each_constitutive_law(
+ [](auto && phasefield) { 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);
prev_dam = dam;
}
for (auto && values : zip(*damage, *blocked_dofs)) {
auto & dam = std::get<0>(values);
auto & blocked = std::get<1>(values);
- dam = std::min(1.,dam);
+ dam = std::min(1., dam);
if (!blocked) {
blocked = Math::are_float_equal(dam, 1.);
}
}
- for (auto & phasefield : phasefields) {
- phasefield->afterSolveStep();
- }
+ for_each_constitutive_law(
+ [](auto && phasefield) { phasefield.afterSolveStep(); });
}
/* -------------------------------------------------------------------------- */
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);
- }
+ for_each_constitutive_law([](auto && phasefield) {
+ 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();
this->synchronize(SynchronizationTag::_pfm_damage);
- for (auto & phasefield : phasefields) {
- phasefield->computeAllDrivingForces(_not_ghost);
- }
+ for_each_constitutive_law([](auto && phasefield) {
+ phasefield.computeAllDrivingForces(_not_ghost);
+ });
// assemble the forces due to local driving forces
AKANTU_DEBUG_INFO("Assemble residual for local elements");
- for (auto & phasefield : phasefields) {
- phasefield->assembleInternalForces(_not_ghost);
- }
+ for_each_constitutive_law([](auto && phasefield) {
+ phasefield.assembleInternalForces(_not_ghost);
+ });
// assemble the forces due to local driving forces
AKANTU_DEBUG_INFO("Assemble residual for ghost elements");
- for (auto & phasefield : phasefields) {
- phasefield->assembleInternalForces(_ghost);
- }
+ for_each_constitutive_law(
+ [](auto && phasefield) { phasefield.assembleInternalForces(_ghost); });
+}
+
+/* -------------------------------------------------------------------------- */
+void PhaseFieldModel::savePreviousState() {
+ for_each_constitutive_law(
+ [](auto && phasefield) { phasefield.savePreviousState(); });
}
/* -------------------------------------------------------------------------- */
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);
}
/* -------------------------------------------------------------------------- */
Int PhaseFieldModel::getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const {
- Int size = 0;
+ Int size = Parent::getNbData(elements, tag);
Int nb_nodes_per_element = 0;
for (const Element & el : elements) {
nb_nodes_per_element += Mesh::getNbNodesPerElement(el.type);
}
switch (tag) {
- case SynchronizationTag::_phasefield_id: {
- size += elements.size() * sizeof(Int);
- break;
- }
case SynchronizationTag::_for_dump: {
// damage
size += nb_nodes_per_element * sizeof(Real);
break;
}
case SynchronizationTag::_pfm_damage: {
size += nb_nodes_per_element * sizeof(Real);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
return size;
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::packData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) const {
+ Parent::packData(buffer, elements, tag);
switch (tag) {
- case SynchronizationTag::_phasefield_id: {
- packElementalDataHelper(phasefield_index, buffer, elements, false,
- getFEEngine());
- break;
- }
case SynchronizationTag::_for_dump: {
packNodalDataHelper(*damage, buffer, elements, mesh);
break;
}
case SynchronizationTag::_pfm_damage: {
packNodalDataHelper(*damage, buffer, elements, mesh);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::unpackData(CommunicationBuffer & buffer,
const Array<Element> & elements,
const SynchronizationTag & tag) {
- AKANTU_DEBUG_IN();
-
+ Parent::unpackData(buffer, elements, tag);
switch (tag) {
- case SynchronizationTag::_phasefield_id: {
- for (auto && element : elements) {
- Idx recv_phase_index;
- buffer >> recv_phase_index;
- Idx & phase_index = phasefield_index(element);
- if (phase_index != Idx(-1)) {
- continue;
- }
-
- // add ghosts element to the correct phasefield
- phase_index = recv_phase_index;
- Idx index = phasefields[phase_index]->addElement(element);
- phasefield_local_numbering(element) = index;
- }
- break;
- }
case SynchronizationTag::_for_dump: {
unpackNodalDataHelper(*damage, buffer, elements, mesh);
break;
}
case SynchronizationTag::_pfm_damage: {
unpackNodalDataHelper(*damage, buffer, elements, mesh);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
Int PhaseFieldModel::getNbData(const Array<Idx> & indexes,
const SynchronizationTag & tag) const {
Int size = 0;
Int nb_nodes = indexes.size();
switch (tag) {
case SynchronizationTag::_for_dump: {
size += nb_nodes * sizeof(Real);
break;
}
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<Idx> & indexes,
const SynchronizationTag & tag) const {
switch (tag) {
case SynchronizationTag::_for_dump: {
packDOFDataHelper(*damage, buffer, indexes);
break;
}
case SynchronizationTag::_pfm_damage: {
packDOFDataHelper(*damage, buffer, indexes);
break;
}
default: {
AKANTU_ERROR("Unknown ghost synchronization tag : " << tag);
}
}
}
/* -------------------------------------------------------------------------- */
void PhaseFieldModel::unpackData(CommunicationBuffer & buffer,
const Array<Idx> & indexes,
const SynchronizationTag & tag) {
switch (tag) {
case SynchronizationTag::_for_dump: {
unpackDOFDataHelper(*damage, buffer, indexes);
break;
}
case SynchronizationTag::_pfm_damage: {
unpackDOFDataHelper(*damage, buffer, indexes);
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*/, Int /*unused*/, ElementKind element_kind) {
if (field_name == "partitions") {
return mesh.createElementalField<Int, dumpers::ElementPartitionField>(
mesh.getConnectivities(), group_name, this->spatial_dimension,
element_kind);
}
std::shared_ptr<dumpers::Field> field;
return field;
}
-/* -------------------------------------------------------------------------- */
-ElementTypeMapArray<Real> &
-PhaseFieldModel::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 & phasefield : phasefields) {
- if (phasefield->isInternal<Real>(field_name, kind)) {
- phasefield->flattenInternal(field_name, *internal_flat, ghost_type, kind);
- }
- }
-
- return *internal_flat;
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::inflateInternal(const std::string & field_name,
- const ElementTypeMapArray<Real> & field,
- ElementKind kind, GhostType ghost_type) {
-
- for (auto & phasefield : phasefields) {
- if (phasefield->isInternal<Real>(field_name, kind)) {
- phasefield->inflateInternal(field_name, field, ghost_type, kind);
- } else {
- AKANTU_ERROR("A internal of name \'"
- << field_name
- << "\' has not been defined in the phasefield");
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::computeStrain(GhostType ghost_type) {
- for (auto & phasefield : phasefields) {
- phasefield->computeStrain(ghost_type);
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::savePreviousDamage() {
- for (auto & phasefield : phasefields) {
- phasefield->savePreviousDamage();
- }
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseFieldModel::savePreviousState() {
- for (auto & phasefield : phasefields) {
- phasefield->savePreviousState();
- }
-}
-
-/* -------------------------------------------------------------------------- */
-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 1765db579..4f1cc8ff3 100644
--- a/src/model/phase_field/phase_field_model.hh
+++ b/src/model/phase_field/phase_field_model.hh
@@ -1,379 +1,257 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "constitutive_laws_handler.hh"
#include "fe_engine.hh"
#include "model.hh"
-/* -------------------------------------------------------------------------- */
-#include <array>
+#include "phasefield_selector.hh"
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_PHASE_FIELD_MODEL_HH__
-#define __AKANTU_PHASE_FIELD_MODEL_HH__
+#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<Idx>,
+class PhaseFieldModel : public ConstitutiveLawsHandler<PhaseField, Model>,
public BoundaryCondition<PhaseFieldModel> {
+ using Parent = ConstitutiveLawsHandler<PhaseField, Model>;
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
using FEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
PhaseFieldModel(Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "phase_field_model",
std::shared_ptr<DOFManager> dof_manager = nullptr,
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;
+ [[nodiscard]] 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;
- /// function to print the containt of the class
- void printself(std::ostream & stream, int indent = 0) const override;
-
protected:
/* ------------------------------------------------------------------------ */
- TimeStepSolverType getDefaultSolverType() const override;
+ [[nodiscard]] TimeStepSolverType getDefaultSolverType() const override;
std::tuple<ID, TimeStepSolverType>
getDefaultSolverID(const AnalysisMethod & method) override;
- ModelSolverOptions
+ [[nodiscard]] ModelSolverOptions
getDefaultSolverOptions(const TimeStepSolverType & type) 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<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(GhostType ghost_type);
+ // save fields history
+ void savePreviousState();
+
/* ------------------------------------------------------------------------ */
/* 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;
+ void computeNonLocalContribution(GhostType /*ghost_type*/) override{};
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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;
- Int getNbData(const Array<Idx> & indexes,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] Int getNbData(const Array<Idx> & indexes,
+ const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Idx> & indexes,
const SynchronizationTag & tag) const override;
void unpackData(CommunicationBuffer & buffer, const Array<Idx> & indexes,
const SynchronizationTag & tag) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
-protected:
- /// Compute dissipated energy for an element type and phasefield index
- Real getEnergy(ElementType type, Idx index);
-
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 SolidMechanicsModel::blocked_dofs array
- AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(BlockedDOFs, blocked_dofs);
-
/// get the PhaseFieldModel::blocked_dofs vector
AKANTU_GET_MACRO_DEREF_PTR(BlockedDOFs, blocked_dofs);
+ /// get the PhaseFieldModel::blocked_dofs vector
+ AKANTU_GET_MACRO_DEREF_PTR_NOT_CONST(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(Idx mat_index);
-
- /// get a particular phasefield (by phasefield index)
- inline const PhaseField & getPhaseField(Idx 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 Idx getPhaseFieldIndex(const std::string & name) const;
-
- /// give the number of phasefields
- inline Idx getNbPhaseFields() const { return phasefields.size(); }
-
- /// give the phasefield internal index from its id
- Idx getInternalIndexFromID(const ID & id) const;
-
- /**
- * @brief Returns the total dissipated energy
- *
- */
- Real getEnergy();
+ /// Returns the total dissipated energy
+ [[nodiscard]] virtual Real getEnergy(const ID & energy_id = "dissipated");
/// Compute dissipated energy for an individual element
- Real getEnergy(const Element & element) {
- return getEnergy(element.type, element.element);
- }
+ [[nodiscard]] virtual Real getEnergy(const ID & energy_id,
+ const Element & element);
/// Compute dissipated energy for an element group
- Real getEnergy(const ID & group_id);
+ [[nodiscard]] virtual Real getEnergy(const ID & energy_id,
+ const ID & group_id);
- AKANTU_GET_MACRO(PhaseFieldByElement, phasefield_index,
- const ElementTypeMapArray<Idx> &);
- AKANTU_GET_MACRO(PhaseFieldLocalNumbering, phasefield_local_numbering,
- const ElementTypeMapArray<Idx> &);
+ FEEngine & getFEEngineBoundary(const ID & name = "") override;
- /// vectors containing local material element index for each global element
- /// index
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PhaseFieldByElement, phasefield_index,
- Idx);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PhaseFieldByElement, phasefield_index, Idx);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PhaseFieldLocalNumbering,
- phasefield_local_numbering, Idx);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PhaseFieldLocalNumbering,
- phasefield_local_numbering, Idx);
+ void
+ setPhaseFieldSelector(const std::shared_ptr<PhaseFieldSelector> & selector) {
+ this->setConstitutiveLawSelector(selector);
+ }
- AKANTU_GET_MACRO_NOT_CONST(PhaseFieldSelector, *phasefield_selector,
- PhaseFieldSelector &);
+ PhaseField & getPhaseField(const ID & id) { return getConstitutiveLaw(id); }
+ PhaseField & getPhaseField(Idx id) { return getConstitutiveLaw(id); }
- AKANTU_SET_MACRO(PhaseFieldSelector, phasefield_selector,
- std::shared_ptr<PhaseFieldSelector>);
+ [[nodiscard]] const PhaseField & getPhaseField(const ID & id) const {
+ return getConstitutiveLaw(id);
+ }
+ [[nodiscard]] const PhaseField & getPhaseField(Idx id) const {
+ return getConstitutiveLaw(id);
+ }
- FEEngine & getFEEngineBoundary(const ID & name = "") override;
+ /// give the number of phasefield materials
+ [[nodiscard]] inline auto getNbPhaseFields() const {
+ return this->getNbConstitutiveLaws();
+ }
/* ------------------------------------------------------------------------ */
/* 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,
Int spatial_dimension, ElementKind kind) override;
- //! flatten a given phasefield internal field
- ElementTypeMapArray<Real> &
- flattenInternal(const std::string & field_name, ElementKind kind,
- GhostType ghost_type = _not_ghost);
-
- //! inverse operation of the flatten
- void inflateInternal(const std::string & field_name,
- const ElementTypeMapArray<Real> & field,
- ElementKind kind, GhostType ghost_type = _not_ghost);
-
- /// Compute strain tensors from grad_u tensors
- void computeStrain(GhostType ghost_type);
-
- /// Save previous damage
- void savePreviousDamage();
-
- /// Save previous damage
- void savePreviousState();
-
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// number of iterations
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<Idx> phasefield_index;
-
- /// Arrays containing the position in the element filter of the phasefield
- /// (phasefield's 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, Idx> phasefields_names_to_id;
-
- /// list of used phasefields
- std::vector<std::unique_ptr<PhaseField>> phasefields;
-
- using flatten_internal_map =
- std::map<std::pair<std::string, ElementKind>,
- std::unique_ptr<ElementTypeMapArray<Real>>>;
-
- /// tells if the phasefields are instantiated
- flatten_internal_map registered_internals;
-
- /// tells if the phasefield are instantiated
- bool are_phasefields_instantiated{false};
};
} // namespace akantu
+#include "phasefield.hh"
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
-#include "parser.hh"
-#include "phasefield.hh"
-
#include "phase_field_model_inline_impl.hh"
/* -------------------------------------------------------------------------- */
#endif
diff --git a/src/model/phase_field/phase_field_model_inline_impl.hh b/src/model/phase_field/phase_field_model_inline_impl.hh
index 0c7f2aaa6..8c8f26057 100644
--- a/src/model/phase_field/phase_field_model_inline_impl.hh
+++ b/src/model/phase_field/phase_field_model_inline_impl.hh
@@ -1,90 +1,33 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(Idx mat_index) {
- AKANTU_DEBUG_ASSERT(mat_index < Idx(phasefields.size()),
- "The model " << id << " has no phasefield no "
- << mat_index);
- return *phasefields[mat_index];
-}
-
-/* -------------------------------------------------------------------------- */
-inline const PhaseField & PhaseFieldModel::getPhaseField(Idx mat_index) const {
- AKANTU_DEBUG_ASSERT(mat_index < Idx(phasefields.size()),
- "The model " << id << " has no phasefield no "
- << mat_index);
- return *phasefields[mat_index];
-}
-
-/* -------------------------------------------------------------------------- */
-inline PhaseField & PhaseFieldModel::getPhaseField(const std::string & 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 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
+namespace akantu {} // 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 588cfdb04..784c54880 100644
--- a/src/model/phase_field/phasefield.cc
+++ b/src/model/phase_field/phasefield.cc
@@ -1,474 +1,293 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "aka_common.hh"
#include "phase_field_model.hh"
-#include <array>
+#include "random_internal_field.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
-PhaseField::PhaseField(PhaseFieldModel & model, const ID & id)
- : Parsable(ParserType::_phasefield, id), id(id), fem(model.getFEEngine()),
- model(model), g_c("g_c", *this),
- spatial_dimension(this->model.getSpatialDimension()),
- element_filter("element_filter", id), damage_on_qpoints("damage", *this),
- gradd("grad_d", *this), phi("phi", *this), grad_u("grad_u", *this),
- strain("strain", *this), driving_force("driving_force", *this),
- driving_energy("driving_energy", *this),
- damage_energy("damage_energy", *this),
- damage_energy_density("damage_energy_density", *this),
- dissipated_energy("dissipated_energy", *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, Int dim, const Mesh & mesh,
- FEEngine & fe_engine, const ID & id)
- : Parsable(ParserType::_phasefield, id), id(id), fem(fe_engine),
- model(model), g_c("g_c", *this),
- spatial_dimension(this->model.getSpatialDimension()),
- element_filter("element_filter", id),
- damage_on_qpoints("damage", *this, dim, fe_engine, this->element_filter),
- gradd("grad_d", *this, dim, fe_engine, this->element_filter),
- phi("phi", *this, dim, fe_engine, this->element_filter),
- grad_u("grad_u", *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),
- driving_energy("driving_energy", *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),
- dissipated_energy("dissipated_energy", *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() = 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");
- registerParam("Plane_Stress", plane_stress, false,
- _pat_parsable | _pat_readable, "Is plane stress");
- registerParam("finite_deformation", finite_deformation, false,
- _pat_parsable | _pat_readable, "Is finite deformation");
- registerParam("isotropic", isotropic, true, _pat_parsable | _pat_readable,
- "Use isotropic formulation");
-
- damage_on_qpoints.initialize(1);
- damage_on_qpoints.setDefaultValue(0.);
-
- phi.initialize(1);
- driving_force.initialize(1);
-
- driving_energy.initialize(spatial_dimension);
- gradd.initialize(spatial_dimension);
- g_c.initialize(1);
-
- grad_u.initialize(spatial_dimension * spatial_dimension);
- strain.initialize(spatial_dimension * spatial_dimension);
-
- dissipated_energy.initialize(1);
-
- damage_energy_density.initialize(1);
- damage_energy.initialize(spatial_dimension * spatial_dimension);
-
- std::cout << "PhaseField g_c: " << this->g_c << std::endl;
- std::cout << "PhaseField l0: " << this->l0 << std::endl;
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseField::initPhaseField() {
- AKANTU_DEBUG_IN();
-
+PhaseField::PhaseField(PhaseFieldModel & model, const ID & id,
+ const ID & fe_engine_id)
+ : Parent(model, id, model.getSpatialDimension(), _ek_regular, fe_engine_id),
+ g_c(this->registerInternal<Real, DefaultRandomInternalField>(
+ "g_c", 1, fe_engine_id)),
+ damage_on_qpoints(this->registerInternal("damage", 1, fe_engine_id)),
+ gradd(this->registerInternal("grad_d", spatial_dimension, fe_engine_id)),
+ phi(this->registerInternal("phi", 1, fe_engine_id)),
+ strain(this->registerInternal(
+ "strain", spatial_dimension * spatial_dimension, fe_engine_id)),
+ driving_force(this->registerInternal("driving_force", 1, fe_engine_id)),
+ driving_energy(this->registerInternal("driving_energy", spatial_dimension,
+ fe_engine_id)),
+ damage_energy(this->registerInternal(
+ "damage_energy", spatial_dimension * spatial_dimension,
+ fe_engine_id)),
+ damage_energy_density(
+ this->registerInternal("damage_energy_density", 1, fe_engine_id)),
+ dissipated_energy(
+ this->registerInternal("dissipated_energy", 1, fe_engine_id)) {
+
+ this->phi.setDefaultValue(0.);
+ this->damage_on_qpoints.setDefaultValue(0.);
this->phi.initializeHistory();
this->damage_on_qpoints.initializeHistory();
- this->savePreviousDamage();
- 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_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();
+ this->registerParam("l0", l0, Real(0.), _pat_parsable | _pat_readable,
+ "length scale parameter");
+ this->registerParam("gc", g_c, _pat_parsable | _pat_readable,
+ "critical local fracture energy density");
+ this->registerParam("E", E, _pat_parsable | _pat_readable, "Young's modulus");
+ this->registerParam("nu", nu, _pat_parsable | _pat_readable, "Poisson ratio");
+ this->registerParam("isotropic", isotropic, true,
+ _pat_parsable | _pat_readable,
+ "Use isotropic formulation");
+ this->registerParam("Plane_Stress", plane_stress, false,
+ _pat_parsable | _pat_readable, "Is plane stress");
}
/* -------------------------------------------------------------------------- */
void PhaseField::updateInternalParameters() {
this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - 2 * this->nu));
if (this->plane_stress) {
this->lambda = this->nu * this->E / ((1 + this->nu) * (1 - this->nu));
}
this->mu = this->E / (2 * (1 + this->nu));
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseField::computeStrain(GhostType ghost_type) {
- Int dim = model.getSpatialDimension();
-
- if (not this->finite_deformation) {
-
- for (const auto & type : element_filter.elementTypes(dim, ghost_type)) {
- for (auto && tuple :
- zip(make_view(this->grad_u(type, ghost_type), dim, dim),
- make_view(this->strain(type, ghost_type), dim, dim))) {
-
- const auto & grad_u_quad = std::get<0>(tuple);
- auto & strain_quad = std::get<1>(tuple);
-
- strain_quad = (grad_u_quad + grad_u_quad.transpose()) / 2.;
- }
- }
-
- } else {
-
- for (const auto & type : element_filter.elementTypes(dim, ghost_type)) {
- for (auto && tuple :
- zip(make_view(this->grad_u(type, ghost_type), dim, dim),
- make_view(this->strain(type, ghost_type), dim, dim))) {
-
- const auto & grad_u_quad = std::get<0>(tuple);
- auto & strain_quad = std::get<1>(tuple);
-
- strain_quad = (grad_u_quad.transpose() * grad_u_quad +
- grad_u_quad.transpose() + grad_u_quad) /
- 2.;
- }
- }
- }
+ Parent::updateInternalParameters();
}
/* -------------------------------------------------------------------------- */
void PhaseField::computeAllDrivingForces(GhostType ghost_type) {
+ auto & damage = handler.getDamage();
+ auto & fem = this->getFEEngine();
- AKANTU_DEBUG_IN();
-
- Int spatial_dimension = model.getSpatialDimension();
- auto & damage = model.getDamage();
-
- for (const auto & type :
- element_filter.elementTypes(spatial_dimension, ghost_type)) {
- auto & elem_filter = element_filter(type, ghost_type);
-
+ for (const auto & type : this->getElementFilter().elementTypes(
+ this->spatial_dimension, ghost_type)) {
+ auto & elem_filter = this->getElementFilter(type, ghost_type);
if (elem_filter.empty()) {
continue;
}
// compute the damage on quadrature points
auto & damage_interpolated = damage_on_qpoints(type, ghost_type);
fem.interpolateOnIntegrationPoints(damage, damage_interpolated, 1, type,
ghost_type);
auto & gradd_vect = gradd(type, _not_ghost);
/// compute @f$\nabla u@f$
fem.gradientOnIntegrationPoints(damage, gradd_vect, 1, type, ghost_type,
elem_filter);
computeDrivingForce(type, ghost_type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::assembleInternalForces(GhostType ghost_type) {
+ Array<Real> & internal_force = handler.getInternalForce();
+ auto & fem = this->getFEEngine();
- 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);
+ for (auto type : getElementFilter().elementTypes(_ghost_type = ghost_type)) {
+ auto & elem_filter = getElementFilter(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);
auto & driving_force_vect = driving_force(type, ghost_type);
- Array<Real> nt_driving_force(nb_quadrature_points, nb_nodes_per_element);
+ Array<Real> nt_driving_force(0, nb_nodes_per_element);
fem.computeNtb(driving_force_vect, nt_driving_force, type, ghost_type,
elem_filter);
- Array<Real> int_nt_driving_force(nb_element * nb_quadrature_points,
- nb_nodes_per_element);
+ Array<Real> int_nt_driving_force(0, nb_nodes_per_element);
fem.integrate(nt_driving_force, int_nt_driving_force, nb_nodes_per_element,
type, ghost_type, elem_filter);
+ handler.getDOFManager().assembleElementalArrayLocalArray(
+ int_nt_driving_force, internal_force, type, ghost_type, -1,
+ elem_filter);
+
// damage_energy_on_qpoints = gc*l0 = scalar
auto & driving_energy_vect = driving_energy(type, ghost_type);
- Array<Real> bt_driving_energy(nb_element * nb_quadrature_points,
- nb_nodes_per_element);
+ Array<Real> bt_driving_energy(0, nb_nodes_per_element);
fem.computeBtD(driving_energy_vect, bt_driving_energy, type, ghost_type,
elem_filter);
- Array<Real> int_bt_driving_energy(nb_element, nb_nodes_per_element);
+ Array<Real> int_bt_driving_energy(0, nb_nodes_per_element);
fem.integrate(bt_driving_energy, int_bt_driving_energy,
nb_nodes_per_element, type, ghost_type, elem_filter);
- model.getDOFManager().assembleElementalArrayLocalArray(
- int_nt_driving_force, internal_force, type, ghost_type, -1,
- elem_filter);
-
- model.getDOFManager().assembleElementalArrayLocalArray(
+ handler.getDOFManager().assembleElementalArrayLocalArray(
int_bt_driving_energy, 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");
+ auto & fem = this->getFEEngine();
- for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
- auto & elem_filter = element_filter(type, ghost_type);
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, ghost_type)) {
+ auto & elem_filter = getElementFilter(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(
+ handler.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(
+ handler.getDOFManager().assembleElementalMatricesToMatrix(
"K", "damage", *K_b, type, _not_ghost, _symmetric, elem_filter);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::computeDissipatedEnergyByElements() {
- AKANTU_DEBUG_IN();
+ const Array<Real> & damage = handler.getDamage();
+ auto & fem = this->getFEEngine();
- const Array<Real> & damage = model.getDamage();
-
- for (auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) {
-
- Array<Idx> & elem_filter = element_filter(type, _not_ghost);
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, _not_ghost)) {
+ Array<Idx> & elem_filter = getElementFilter(type, _not_ghost);
if (elem_filter.empty()) {
continue;
}
Array<Real> & damage_interpolated = damage_on_qpoints(type, _not_ghost);
// compute the damage on quadrature points
fem.interpolateOnIntegrationPoints(damage, damage_interpolated, 1, type,
_not_ghost);
Array<Real> & gradd_vect = gradd(type, _not_ghost);
/// compute @f$\nabla u@f$
fem.gradientOnIntegrationPoints(damage, gradd_vect, 1, type, _not_ghost,
elem_filter);
computeDissipatedEnergy(type);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void PhaseField::computeDissipatedEnergy(ElementType /*unused*/) {
- AKANTU_DEBUG_IN();
AKANTU_TO_IMPLEMENT();
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-Real PhaseField::getEnergy() {
- AKANTU_DEBUG_IN();
+PhaseFieldFactory & PhaseField::getFactory() {
+ return PhaseFieldFactory::getInstance();
+}
+
+/* -------------------------------------------------------------------------- */
+Real PhaseField::getEnergy(const ID & energy_id) {
+ if (energy_id != "dissipated") {
+ return 0.;
+ }
+
Real edis = 0.;
+ auto & fem = this->getFEEngine();
computeDissipatedEnergyByElements();
/// integrate the dissipated energy for each type of elements
- for (auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, _not_ghost)) {
edis += fem.integrate(dissipated_energy(type, _not_ghost), type, _not_ghost,
- element_filter(type, _not_ghost));
+ getElementFilter(type, _not_ghost));
}
- AKANTU_DEBUG_OUT();
return edis;
}
/* -------------------------------------------------------------------------- */
-Real PhaseField::getEnergy(ElementType type, Idx index) {
- Real edis = 0.;
-
- Vector<Real> edis_on_quad_points(fem.getNbIntegrationPoints(type));
-
- computeDissipatedEnergyByElement(type, index, edis_on_quad_points);
-
- edis = fem.integrate(edis_on_quad_points, Element{type, index, _not_ghost});
-
- return edis;
-}
+Real PhaseField::getEnergy(const ID & energy_id, const Element & element) {
+ if (energy_id != "dissipated") {
+ return 0.;
+ }
-/* -------------------------------------------------------------------------- */
-Real PhaseField::getEnergy(const Element & element) {
- return getEnergy(element.type, element.element);
+ auto & fem = this->getFEEngine();
+ Vector<Real> edis_on_quad_points(fem.getNbIntegrationPoints(element.type));
+ computeDissipatedEnergyByElement(element.type, element.element,
+ edis_on_quad_points);
+ return fem.integrate(edis_on_quad_points, element);
}
/* -------------------------------------------------------------------------- */
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();
- // }
- // }
-
- if (this->phi.hasHistory()) {
- this->phi.saveCurrentValues();
- }
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-void PhaseField::savePreviousDamage() {
- if (this->damage_on_qpoints.hasHistory()) {
- this->damage_on_qpoints.saveCurrentValues();
- }
-}
-
-/* -------------------------------------------------------------------------- */
-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 ae583bfc8..9723b3538 100644
--- a/src/model/phase_field/phasefield.hh
+++ b/src/model/phase_field/phasefield.hh
@@ -1,377 +1,209 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_factory.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 "constitutive_law.hh"
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_PHASEFIELD_HH__
-#define __AKANTU_PHASEFIELD_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 {
+ Factory<PhaseField, ID, Int, const ID &, PhaseFieldModel &, const ID &>;
+class PhaseField : public ConstitutiveLaw<PhaseFieldModel> {
+ using Parent = ConstitutiveLaw<PhaseFieldModel>;
/* ------------------------------------------------------------------------ */
/* 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, Int dim, const Mesh & mesh,
- FEEngine & fe_engine, const ID & id = "");
-
- /// Destructor
- ~PhaseField() override;
-
-protected:
- void initialize();
+ PhaseField(PhaseFieldModel & model, const ID & id = "",
+ const ID & fe_engine_id = "");
/* ------------------------------------------------------------------------ */
/* 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 initPhaseField() { Parent::initConstitutiveLaw(); }
+ void initConstitutiveLaw() override { this->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 Int addElement(const Element & element);
-
- /// function to print the contain of the class
- void printself(std::ostream & stream, int indent = 0) const override;
-
protected:
/// compute the dissipated energy by element
void computeDissipatedEnergyByElements();
- /// add an element to the local mesh filter
- inline Int addElement(const ElementType & type, Idx element,
- const GhostType & ghost_type);
-
- /// resize the internals arrrays
- virtual void resizeInternals();
-
/// function called to updatet the internal parameters when the
/// modifiable parameters are modified
- virtual void updateInternalParameters();
+ void updateInternalParameters() override;
// constitutive law for driving force
virtual void computeDrivingForce(ElementType /* el_type */,
GhostType /* ghost_type */ = _not_ghost) {
AKANTU_TO_IMPLEMENT();
}
/// compute the dissiapted energy
virtual void computeDissipatedEnergy(ElementType el_type);
/// compute the dissipated energy for an element
virtual void
computeDissipatedEnergyByElement(const Element & /*element*/,
Vector<Real> & /*edis_on_quad_points*/) {
AKANTU_TO_IMPLEMENT();
}
/// compute the dissipated energy for an element
virtual void
computeDissipatedEnergyByElement(ElementType /*type*/, Idx /*index*/,
Vector<Real> & /*edis_on_quad_points*/) {
AKANTU_TO_IMPLEMENT();
}
- /* ------------------------------------------------------------------------ */
- /* DataAccessor inherited members */
- /* ------------------------------------------------------------------------ */
-public:
- 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 */
/* ------------------------------------------------------------------------ */
-protected:
- /// return the damage energyfor the provided element
- virtual Real getEnergy(ElementType type, Idx index);
-
public:
+ /// static method to reteive the material factory
+ static PhaseFieldFactory & getFactory();
+
/// return the damage energyfor the subset of elements contained
/// by the phasefield
- virtual Real getEnergy();
+ [[nodiscard]] Real getEnergy(const ID & energy_id) override;
/// Compute dissipated energy for an individual element
- Real getEnergy(const Element & element);
-
- AKANTU_GET_MACRO(Name, name, const std::string &);
-
- AKANTU_GET_MACRO(Model, model, const PhaseFieldModel &)
-
- AKANTU_GET_MACRO(ID, id, const ID &);
+ [[nodiscard]] Real getEnergy(const ID & energy_id,
+ const Element & element) override;
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_AUTO(Strain, strain);
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Strain, strain);
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage_on_qpoints, Real);
-
- AKANTU_GET_MACRO_NOT_CONST(Damage, damage_on_qpoints,
- ElementTypeMapArray<Real> &);
- AKANTU_GET_MACRO(Damage, damage_on_qpoints,
- const ElementTypeMapArray<Real> &);
-
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, Idx);
-
- AKANTU_GET_MACRO(ElementFilter, element_filter,
- const ElementTypeMapArray<Idx> &);
-
- 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 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;
-
- 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);
-
- /// Compute strain tensors from grad_u tensors
- void computeStrain(GhostType ghost_type);
-
- /// Save previous damage, to call after solving loading step when using
- /// penalization
- void savePreviousDamage();
+ AKANTU_GET_MACRO_AUTO_NOT_CONST(Damage, damage_on_qpoints);
+ AKANTU_GET_MACRO_AUTO(Damage, damage_on_qpoints);
/* ------------------------------------------------------------------------ */
/* 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<Int> *> 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;
+ Real l0{0.};
/// Young's modulus
- Real E;
+ Real E{0.};
/// Poisson ratio
- Real nu;
+ Real nu{0.};
/// Finite deformation
bool plane_stress{false};
/// Finite deformation
bool finite_deformation{false};
/// Isotropic formulation
bool isotropic{true};
/// Lame's first parameter
- Real lambda;
+ Real lambda{0.};
/// Lame's second paramter
- Real mu;
+ Real mu{0.};
- /// spatial dimension
- Int spatial_dimension;
-
- /// list of element handled by the phasefield
- ElementTypeMapArray<Idx> element_filter;
+ /// critical energy release rate
+ // Real g_c;
+ DefaultRandomInternalField<Real> & g_c;
/// damage arrays ordered by element types
- InternalPhaseField<Real> damage_on_qpoints;
+ InternalField<Real> & damage_on_qpoints;
/// grad_d arrays ordered by element types
- InternalPhaseField<Real> gradd;
+ InternalField<Real> & gradd;
/// phi arrays ordered by element types
- InternalPhaseField<Real> phi;
-
- /// strain arrays ordered by element types
- InternalPhaseField<Real> grad_u;
+ InternalField<Real> & phi;
/// strain arrays ordered by element types
- InternalPhaseField<Real> strain;
+ InternalField<Real> & strain;
/// driving force ordered by element types
- InternalPhaseField<Real> driving_force;
+ InternalField<Real> & driving_force;
/// driving energy ordered by element types
- InternalPhaseField<Real> driving_energy;
+ InternalField<Real> & driving_energy;
/// damage energy ordered by element types
- InternalPhaseField<Real> damage_energy;
+ InternalField<Real> & damage_energy;
/// damage energy density ordered by element types
- InternalPhaseField<Real> damage_energy_density;
+ InternalField<Real> & damage_energy_density;
/// dissipated energy by element
- InternalPhaseField<Real> dissipated_energy;
+ InternalField<Real> & dissipated_energy;
};
-/// 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.hh"
#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); \
+namespace akantu {
+namespace {
+ template <template <Int> class PF> bool instantiatePhaseField(const ID & id) {
+ return PhaseFieldFactory::getInstance().registerAllocator(
+ id, [](Int dim, const ID &, PhaseFieldModel & model, const ID & id) {
+ return tuple_dispatch<AllSpatialDimensions>(
+ [&](auto && _) -> std::unique_ptr<PhaseField> {
+ constexpr auto && dim_ = aka::decay_v<decltype(_)>;
+ return std::make_unique<PF<dim_>>(model, id);
+ },
+ dim);
+ });
}
-
-#define INSTANTIATE_PHASEFIELD(id, phase_name) \
- static bool phasefield_is_allocated_##id [[gnu::unused]] = \
- PhaseFieldFactory::getInstance().registerAllocator( \
- #id, PHASEFIELD_DEFAULT_ALLOCATOR(id, phase_name))
+} // namespace
+} // namespace akantu
#endif
diff --git a/src/model/phase_field/phasefield_inline_impl.hh b/src/model/phase_field/phasefield_inline_impl.hh
index 381413de2..fe4654d03 100644
--- a/src/model/phase_field/phasefield_inline_impl.hh
+++ b/src/model/phase_field/phasefield_inline_impl.hh
@@ -1,353 +1,41 @@
/**
* @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_HH__
#define __AKANTU_PHASEFIELD_INLINE_IMPL_HH__
-namespace akantu {
-
-/* -------------------------------------------------------------------------- */
-inline Int PhaseField::addElement(const ElementType & type, Idx element,
- const GhostType & ghost_type) {
- Array<Int> & el_filter = this->element_filter(type, ghost_type);
- el_filter.push_back(element);
- return el_filter.size() - 1;
-}
-
-/* -------------------------------------------------------------------------- */
-inline Int 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<Int>(InternalPhaseField<Int> & 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<Int>(InternalPhaseField<Int> & vect) {
- 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 {
- AKANTU_TO_IMPLEMENT();
-}
-
-template <>
-inline bool
-PhaseField::isInternal<Real>(const ID & id,
- const 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);
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-void PhaseField::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 phasefield "
- << this->name);
- }
-
- const InternalPhaseField<T> & internal_field =
- this->template getInternal<T>(field_id);
-
- const FEEngine & fe_engine = internal_field.getFEEngine();
- const Mesh & 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
- Int nb_element_dst = mesh.getNbElement(type, ghost_type);
- // number of quadrature points per elem
- Int nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
- // number of data per quadrature point
- Int nb_data_per_quad = internal_field.getNbComponent();
-
- if (!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
- Int nb_data = nb_quad_per_elem * nb_data_per_quad;
-
- Array<Real> & 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 PhaseField::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 phasefield "
- << this->name);
- }
-
- InternalPhaseField<T> & internal_field =
- this->template getInternal<T>(field_id);
- const FEEngine & fe_engine = internal_field.getFEEngine();
-
- for (auto && type : field.elementTypes(spatial_dimension, 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)];
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-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 phasefield "
- << 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));
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline const InternalPhaseField<T> &
-PhaseField::getInternal([[gnu::unused]] const ID & int_id) const {
- AKANTU_TO_IMPLEMENT();
- return NULL;
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline InternalPhaseField<T> &
-PhaseField::getInternal([[gnu::unused]] const ID & int_id) {
- AKANTU_TO_IMPLEMENT();
- return NULL;
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline const InternalPhaseField<Real> &
-PhaseField::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 phasefield "
- << name << "(" << getID()
- << ") does not contain an internal " << int_id
- << " (" << (getID() + ":" + int_id) << ")");
- }
- return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline InternalPhaseField<Real> & PhaseField::getInternal(const ID & int_id) {
- auto it = internal_vectors_real.find(getID() + ":" + int_id);
- if (it == internal_vectors_real.end()) {
- AKANTU_SILENT_EXCEPTION("The phasefield "
- << name << "(" << getID()
- << ") does not contain an internal " << int_id
- << " (" << (getID() + ":" + int_id) << ")");
- }
- return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline const InternalPhaseField<Int> &
-PhaseField::getInternal(const ID & int_id) const {
- auto it = internal_vectors_int.find(getID() + ":" + int_id);
- if (it == internal_vectors_int.end()) {
- AKANTU_SILENT_EXCEPTION("The phasefield "
- << name << "(" << getID()
- << ") does not contain an internal " << int_id
- << " (" << (getID() + ":" + int_id) << ")");
- }
- return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <>
-inline InternalPhaseField<Int> & PhaseField::getInternal(const ID & int_id) {
- auto it = internal_vectors_int.find(getID() + ":" + int_id);
- if (it == internal_vectors_int.end()) {
- AKANTU_SILENT_EXCEPTION("The phasefield "
- << name << "(" << getID()
- << ") does not contain an internal " << int_id
- << " (" << (getID() + ":" + int_id) << ")");
- }
- return *it->second;
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline const Array<T> & PhaseField::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 phasefield " << name << "(" << getID()
- << ") does not contain a vector "
- << vect_id << " [" << e << "]");
- }
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline Array<T> & PhaseField::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 phasefield " << name << "(" << getID()
- << ") does not contain a vector "
- << vect_id << " [" << e << "]");
- }
-}
-
-} // namespace akantu
+namespace akantu {} // namespace akantu
#endif
diff --git a/src/model/phase_field/phasefield_selector.hh b/src/model/phase_field/phasefield_selector.hh
index 5ff6e2569..f290d219d 100644
--- a/src/model/phase_field/phasefield_selector.hh
+++ b/src/model/phase_field/phasefield_selector.hh
@@ -1,157 +1,50 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
+#include "constitutive_law_selector.hh"
#include "element.hh"
#include "mesh.hh"
/* -------------------------------------------------------------------------- */
#include <memory>
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_PHASEFIELD_SELECTOR_HH__
-#define __AKANTU_PHASEFIELD_SELECTOR_HH__
+#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 Idx operator()(const Element & element) {
- if (fallback_selector) {
- return (*fallback_selector)(element);
- }
-
- return fallback_value;
- }
-
- 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 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<Idx> & phasefield_index)
- : phasefield_index(phasefield_index) {}
-
- 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 != -1) {
- return tmp_phase;
- }
- }
-
- return PhaseFieldSelector::operator()(element);
- }
-
-private:
- const ElementTypeMapArray<Idx> & phasefield_index;
-};
-
-/* -------------------------------------------------------------------------- */
-/**
- * Use elemental data to assign phasefields
- */
+using PhaseFieldSelector = ConstitutiveLawSelector;
+using DefaultPhaseFieldSelector = DefaultConstitutiveLawSelector;
template <typename T>
-class ElementDataPhaseFieldSelector : public PhaseFieldSelector {
-public:
- ElementDataPhaseFieldSelector(const ElementTypeMapArray<T> & element_data,
- const PhaseFieldModel & model,
- 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 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
- */
+using ElementDataPhaseFieldSelector =
+ ElementDataConstitutiveLawSelector<T, PhaseFieldModel>;
template <typename T>
-class MeshDataPhaseFieldSelector : public ElementDataPhaseFieldSelector<T> {
-public:
- MeshDataPhaseFieldSelector(const std::string & name,
- const PhaseFieldModel & model,
- Idx first_index = 1);
-};
+using MeshDataPhaseFieldSelector =
+ MeshDataConstitutiveLawSelector<T, PhaseFieldModel>;
} // namespace akantu
-#endif /* __AKANTU_PHASEFIELD_SELECTOR_HH__ */
+#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 ab9ac19d6..fcd5702b1 100644
--- a/src/model/phase_field/phasefield_selector_tmpl.hh
+++ b/src/model/phase_field/phasefield_selector_tmpl.hh
@@ -1,62 +1,30 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#ifndef AKANTU_PHASEFIELD_SELECTOR_TMPL_HH_
+#define AKANTU_PHASEFIELD_SELECTOR_TMPL_HH_
-namespace akantu {
+namespace akantu {} // namespace akantu
-/* -------------------------------------------------------------------------- */
-template <>
-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 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, Idx first_index)
- : ElementDataPhaseFieldSelector<T>(model.getMesh().getData<T>(name), model,
- first_index) {}
-
-} // namespace akantu
-
-#endif /* __AKANTU_PHASEFIELD_SELECTOR_TMPL_HH__ */
+#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 cdf434bba..d903b1189 100644
--- a/src/model/phase_field/phasefields/phasefield_exponential.cc
+++ b/src/model/phase_field/phasefields/phasefield_exponential.cc
@@ -1,152 +1,149 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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)
+template <Int dim>
+PhaseFieldExponential<dim>::PhaseFieldExponential(PhaseFieldModel & model,
+ const ID & id)
: PhaseField(model, id) {}
/* -------------------------------------------------------------------------- */
-void PhaseFieldExponential::updateInternalParameters() {
+template <Int dim> void PhaseFieldExponential<dim>::initPhaseField() {
+ PhaseField::initPhaseField();
+
+ this->dev_dim = dim;
+ if (dim == 2 && !this->plane_stress) {
+ this->dev_dim = 3;
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <Int dim> void PhaseFieldExponential<dim>::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 =
- Matrix<Real>::Identity(spatial_dimension, spatial_dimension) *
- std::get<1>(tuple) * this->l0;
- std::get<0>(tuple) = d;
+ for (const auto & type : getElementFilter().elementTypes(dim, _not_ghost)) {
+ for (auto && [dam, gc] :
+ zip(make_view<dim, dim>(this->damage_energy(type, _not_ghost)),
+ this->g_c(type, _not_ghost))) {
+ dam = Matrix<Real, dim, dim>::Identity() * gc * this->l0;
}
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldExponential::computeDrivingForce(ElementType el_type,
- GhostType ghost_type) {
+template <Int dim>
+void PhaseFieldExponential<dim>::computeDrivingForce(ElementType el_type,
+ GhostType ghost_type) {
+ auto && arguments = zip(
+ this->phi(el_type, ghost_type), this->phi.previous(el_type, ghost_type),
+ make_view(this->strain(el_type, ghost_type), dim, dim));
if (this->isotropic) {
- for (auto && tuple : zip(this->phi(el_type, ghost_type),
- this->phi.previous(el_type, ghost_type),
- make_view(this->strain(el_type, ghost_type),
- spatial_dimension, spatial_dimension))) {
- auto & phi_quad = std::get<0>(tuple);
- auto & phi_hist_quad = std::get<1>(tuple);
- auto & strain = std::get<2>(tuple);
+ for (auto && [phi_quad, phi_hist_quad, strain] : arguments) {
computePhiIsotropicOnQuad(strain, phi_quad, phi_hist_quad);
}
} else {
- for (auto && tuple : zip(this->phi(el_type, ghost_type),
- this->phi.previous(el_type, ghost_type),
- make_view(this->strain(el_type, ghost_type),
- spatial_dimension, spatial_dimension))) {
- auto & phi_quad = std::get<0>(tuple);
- auto & phi_hist_quad = std::get<1>(tuple);
- auto & strain = std::get<2>(tuple);
+ for (auto && [phi_quad, phi_hist_quad, strain] : arguments) {
computePhiOnQuad(strain, phi_quad, phi_hist_quad);
}
}
- for (auto && tuple :
+ for (auto && [phi_quad, driving_force_quad, dam_energy_density_quad,
+ dam_on_quad, driving_energy_quad, damage_energy_quad,
+ gradd_quad, g_c_quad] :
zip(this->phi(el_type, ghost_type),
this->driving_force(el_type, ghost_type),
this->damage_energy_density(el_type, ghost_type),
this->damage_on_qpoints(el_type, _not_ghost),
- make_view(this->driving_energy(el_type, ghost_type),
- spatial_dimension),
- make_view(this->damage_energy(el_type, ghost_type),
- spatial_dimension, spatial_dimension),
- make_view(this->gradd(el_type, ghost_type), spatial_dimension),
+ make_view(this->driving_energy(el_type, ghost_type), dim),
+ make_view(this->damage_energy(el_type, ghost_type), dim, dim),
+ make_view(this->gradd(el_type, ghost_type), dim),
this->g_c(el_type, ghost_type))) {
- auto & phi_quad = std::get<0>(tuple);
- auto & driving_force_quad = std::get<1>(tuple);
- auto & dam_energy_density_quad = std::get<2>(tuple);
- auto & dam_on_quad = std::get<3>(tuple);
- auto & driving_energy_quad = std::get<4>(tuple);
- auto & damage_energy_quad = std::get<5>(tuple);
- auto & gradd_quad = std::get<6>(tuple);
- auto & g_c_quad = std::get<7>(tuple);
-
computeDamageEnergyDensityOnQuad(phi_quad, dam_energy_density_quad,
g_c_quad);
driving_force_quad = dam_on_quad * dam_energy_density_quad - 2 * phi_quad;
driving_energy_quad = damage_energy_quad * gradd_quad;
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldExponential::computeDissipatedEnergy(ElementType el_type) {
+template <Int dim>
+void PhaseFieldExponential<dim>::computeDissipatedEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
- for (auto && tuple :
+ for (auto && [dis_energy, damage, grad_d, g_c] :
zip(this->dissipated_energy(el_type, _not_ghost),
this->damage_on_qpoints(el_type, _not_ghost),
- make_view(this->gradd(el_type, _not_ghost), spatial_dimension),
+ make_view<dim>(this->gradd(el_type, _not_ghost)),
this->g_c(el_type, _not_ghost))) {
-
- this->computeDissipatedEnergyOnQuad(std::get<1>(tuple), std::get<2>(tuple),
- std::get<0>(tuple), std::get<3>(tuple));
+ this->computeDissipatedEnergyOnQuad(damage, grad_d, dis_energy, g_c);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldExponential::computeDissipatedEnergyByElement(
+template <Int dim>
+void PhaseFieldExponential<dim>::computeDissipatedEnergyByElement(
ElementType type, Idx index, Vector<Real> & edis_on_quad_points) {
- auto gradd_it = this->gradd(type).begin(spatial_dimension);
- auto gradd_end = this->gradd(type).begin(spatial_dimension);
- auto damage_it = this->damage_on_qpoints(type).begin();
- auto g_c_it = this->g_c(type).begin();
+ auto && fem = this->getFEEngine();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type);
+
+ auto quad = index * nb_quadrature_points;
- UInt nb_quadrature_points = fem.getNbIntegrationPoints(type);
+ auto gradd_it = make_view<dim>(this->gradd(type)).begin() + quad;
+ auto gradd_end = gradd_it + nb_quadrature_points;
- gradd_it += index * nb_quadrature_points;
- gradd_end += (index + 1) * nb_quadrature_points;
- damage_it += index * nb_quadrature_points;
- g_c_it += index * nb_quadrature_points;
+ auto damage_it = this->damage_on_qpoints(type).begin() + quad;
+ auto g_c_it = this->g_c(type).begin() + quad;
- Real * edis_quad = edis_on_quad_points.data();
+ auto edis_quad = edis_on_quad_points.begin();
for (; gradd_it != gradd_end; ++gradd_it, ++damage_it, ++edis_quad) {
this->computeDissipatedEnergyOnQuad(*damage_it, *gradd_it, *edis_quad,
*g_c_it);
}
}
-void PhaseFieldExponential::computeDissipatedEnergyByElement(
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+void PhaseFieldExponential<dim>::computeDissipatedEnergyByElement(
const Element & element, Vector<Real> & edis_on_quad_points) {
computeDissipatedEnergyByElement(element.type, element.element,
edis_on_quad_points);
}
-INSTANTIATE_PHASEFIELD(exponential, PhaseFieldExponential);
+/* -------------------------------------------------------------------------- */
+template class PhaseFieldExponential<1>;
+template class PhaseFieldExponential<2>;
+template class PhaseFieldExponential<3>;
+
+const bool phase_field_exponential_is_allocated [[maybe_unused]] =
+ instantiatePhaseField<PhaseFieldExponential>("exponential");
} // namespace akantu
diff --git a/src/model/phase_field/phasefields/phasefield_exponential.hh b/src/model/phase_field/phasefields/phasefield_exponential.hh
index 3e858a17f..eb8c21869 100644
--- a/src/model/phase_field/phasefields/phasefield_exponential.hh
+++ b/src/model/phase_field/phasefields/phasefield_exponential.hh
@@ -1,87 +1,89 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#ifndef AKANTU_PHASEFIELD_EXPONENTIAL_HH_
+#define AKANTU_PHASEFIELD_EXPONENTIAL_HH_
namespace akantu {
-class PhaseFieldExponential : public PhaseField {
+
+template <Int dim> class PhaseFieldExponential : public PhaseField {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PhaseFieldExponential(PhaseFieldModel & model, const ID & id = "");
- ~PhaseFieldExponential() override = default;
-
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// compute the dissiapted energy
void computeDissipatedEnergy(ElementType el_type) override;
void
computeDissipatedEnergyByElement(const Element & element,
Vector<Real> & edis_on_quad_points) override;
protected:
void
computeDissipatedEnergyByElement(ElementType type, Idx index,
Vector<Real> & edis_on_quad_points) override;
inline void computePhiOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/, Real & /*phi_hist_quad*/);
inline void computePhiIsotropicOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/,
Real & /*phi_hist_quad*/);
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*/);
inline void
computeDissipatedEnergyOnQuad(const Real & /*dam_quad*/,
const Vector<Real> & /*grad_d_quad */,
Real & /*energy*/, Real & /*g_c_quad*/);
public:
void updateInternalParameters() override;
+
+ void initPhaseField() override;
+
+private:
+ // dimension to consider in deviatoric split
+ Int dev_dim;
};
} // 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 67f290ae9..3d911d35b 100644
--- a/src/model/phase_field/phasefields/phasefield_exponential_inline_impl.hh
+++ b/src/model/phase_field/phasefields/phasefield_exponential_inline_impl.hh
@@ -1,81 +1,88 @@
/**
* Copyright (©) 2022-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <algorithm>
namespace akantu {
-inline void PhaseFieldExponential::computeDissipatedEnergyOnQuad(
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+inline void PhaseFieldExponential<dim>::computeDissipatedEnergyOnQuad(
const Real & dam, const Vector<Real> & grad_d, Real & edis,
Real & g_c_quad) {
edis = 0.;
- for (auto i : arange(spatial_dimension)) {
+ for (auto i : arange(dim)) {
edis += 0.5 * g_c_quad * this->l0 * grad_d[i] * grad_d[i];
}
edis += g_c_quad * dam * dam / (2. * this->l0);
}
/* -------------------------------------------------------------------------- */
-inline void PhaseFieldExponential::computeDamageEnergyDensityOnQuad(
+template <Int dim>
+inline void PhaseFieldExponential<dim>::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;
}
/* -------------------------------------------------------------------------- */
+template <Int dim>
inline void
-PhaseFieldExponential::computePhiOnQuad(const Matrix<Real> & strain_quad,
+PhaseFieldExponential<dim>::computePhiOnQuad(const Matrix<Real> & strain_quad,
Real & phi_quad, Real & phi_hist_quad) {
Real trace = strain_quad.trace();
Real trace_plus = std::max(Real(0.), trace);
- Matrix<Real> strain_dev(spatial_dimension, spatial_dimension);
- strain_dev = strain_quad -
- trace / Real(spatial_dimension) *
- Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
+ Matrix<Real> strain_dev = Matrix<Real>::Zero(dev_dim, dev_dim);
+ Matrix<Real> strain_tmp = Matrix<Real>::Zero(dev_dim, dev_dim);
+ strain_tmp.topLeftCorner(dim, dim) = strain_quad;
+
+ strain_dev = strain_tmp -
+ trace / Real(dev_dim) * Matrix<Real>::Identity(dev_dim, dev_dim);
- Real kpa = this->lambda + 2. * this->mu / Real(spatial_dimension);
+ Real kpa = this->lambda + 2. * this->mu / Real(dev_dim);
phi_quad = 0.5 * kpa * trace_plus * trace_plus +
this->mu * strain_dev.doubleDot(strain_dev);
if (phi_quad < phi_hist_quad) {
phi_quad = phi_hist_quad;
}
}
/* -------------------------------------------------------------------------- */
-inline void PhaseFieldExponential::computePhiIsotropicOnQuad(
+template <Int dim>
+inline void PhaseFieldExponential<dim>::computePhiIsotropicOnQuad(
const Matrix<Real> & strain_quad, Real & phi_quad, Real & phi_hist_quad) {
Real trace = strain_quad.trace();
phi_quad = 0.5 * this->lambda * trace * trace +
this->mu * strain_quad.doubleDot(strain_quad);
if (phi_quad < phi_hist_quad) {
phi_quad = phi_hist_quad;
}
}
} // namespace akantu
diff --git a/src/model/phase_field/phasefields/phasefield_linear.cc b/src/model/phase_field/phasefields/phasefield_linear.cc
index 377f65adf..0ef628d32 100644
--- a/src/model/phase_field/phasefields/phasefield_linear.cc
+++ b/src/model/phase_field/phasefields/phasefield_linear.cc
@@ -1,181 +1,170 @@
/* -------------------------------------------------------------------------- */
#include "phasefield_linear.hh"
#include "aka_common.hh"
#include <tuple>
namespace akantu {
/* -------------------------------------------------------------------------- */
-PhaseFieldLinear::PhaseFieldLinear(PhaseFieldModel & model, const ID & id)
+template <Int dim>
+PhaseFieldLinear<dim>::PhaseFieldLinear(PhaseFieldModel & model, const ID & id)
: PhaseField(model, id) {
registerParam("irreversibility_tol", tol_ir, Real(1e-2),
_pat_parsable | _pat_readable, "Irreversibility tolerance");
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::initPhaseField() {
+template <Int dim> void PhaseFieldLinear<dim>::initPhaseField() {
PhaseField::initPhaseField();
this->gamma = Real(this->g_c) / this->l0 * 27. / (64. * tol_ir * tol_ir);
- this->dim = spatial_dimension;
- if (spatial_dimension == 2 && !this->plane_stress) {
- this->dim = 3;
+ this->dev_dim = dim;
+ if (dim == 2 && !this->plane_stress) {
+ this->dev_dim = 3;
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::updateInternalParameters() {
+template <Int dim> void PhaseFieldLinear<dim>::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);
+ for (const auto & type : getElementFilter().elementTypes(dim, _not_ghost)) {
+ for (auto && tuple :
+ zip(make_view(this->damage_energy(type, _not_ghost), dim, dim),
+ this->g_c(type, _not_ghost))) {
+ Matrix<Real> d(dim, dim);
// eye g_c * l0
d.eye(3. / 4. * std::get<1>(tuple) * this->l0);
std::get<0>(tuple) = d;
}
}
}
/* -------------------------------------------------------------------------- */
-// void PhaseFieldLinear::computeDrivingForce(const 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),
-// std::get<5>(tuple));
-// }
-// }
-
-/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::computeDrivingForce(ElementType el_type,
- GhostType ghost_type) {
+template <Int dim>
+void PhaseFieldLinear<dim>::computeDrivingForce(ElementType el_type,
+ GhostType ghost_type) {
if (this->isotropic) {
- for (auto && tuple : zip(this->phi(el_type, ghost_type),
- make_view(this->strain(el_type, ghost_type),
- spatial_dimension, spatial_dimension))) {
+ for (auto && tuple :
+ zip(this->phi(el_type, ghost_type),
+ make_view(this->strain(el_type, ghost_type), dim, dim))) {
auto & phi_quad = std::get<0>(tuple);
auto & strain = std::get<1>(tuple);
computePhiIsotropicOnQuad(strain, phi_quad);
}
} else {
- for (auto && tuple : zip(this->phi(el_type, ghost_type),
- make_view(this->strain(el_type, ghost_type),
- spatial_dimension, spatial_dimension))) {
+ for (auto && tuple :
+ zip(this->phi(el_type, ghost_type),
+ make_view(this->strain(el_type, ghost_type), dim, dim))) {
auto & phi_quad = std::get<0>(tuple);
auto & strain = std::get<1>(tuple);
computePhiOnQuad(strain, phi_quad);
}
}
for (auto && tuple :
zip(this->phi(el_type, ghost_type),
this->driving_force(el_type, ghost_type),
this->damage_energy_density(el_type, ghost_type),
this->damage_on_qpoints(el_type, _not_ghost),
- make_view(this->driving_energy(el_type, ghost_type),
- spatial_dimension),
- make_view(this->damage_energy(el_type, ghost_type),
- spatial_dimension, spatial_dimension),
- make_view(this->gradd(el_type, ghost_type), spatial_dimension),
+ make_view(this->driving_energy(el_type, ghost_type), dim),
+ make_view(this->damage_energy(el_type, ghost_type), dim, dim),
+ make_view(this->gradd(el_type, ghost_type), dim),
this->g_c(el_type, ghost_type),
this->damage_on_qpoints.previous(el_type, ghost_type))) {
auto & phi_quad = std::get<0>(tuple);
auto & driving_force_quad = std::get<1>(tuple);
auto & dam_energy_density_quad = std::get<2>(tuple);
auto & dam_on_quad = std::get<3>(tuple);
auto & driving_energy_quad = std::get<4>(tuple);
auto & damage_energy_quad = std::get<5>(tuple);
auto & gradd_quad = std::get<6>(tuple);
auto & g_c_quad = std::get<7>(tuple);
auto & dam_prev_quad = std::get<8>(tuple);
- computeDamageEnergyDensityOnQuad(phi_quad, dam_energy_density_quad,
- g_c_quad);
+ computeDamageEnergyDensityOnQuad(phi_quad, dam_energy_density_quad);
Real penalization =
this->gamma * std::min(Real(0.), dam_on_quad - dam_prev_quad);
driving_force_quad = dam_on_quad * dam_energy_density_quad - 2 * phi_quad +
3 * g_c_quad / (8 * this->l0) + penalization;
driving_energy_quad = damage_energy_quad * gradd_quad;
dam_energy_density_quad += this->gamma * (dam_on_quad < dam_prev_quad);
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::computeDissipatedEnergy(ElementType el_type) {
+template <Int dim>
+void PhaseFieldLinear<dim>::computeDissipatedEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
for (auto && tuple :
zip(this->dissipated_energy(el_type, _not_ghost),
this->damage_on_qpoints(el_type, _not_ghost),
this->damage_on_qpoints.previous(el_type, _not_ghost),
- make_view(this->gradd(el_type, _not_ghost), spatial_dimension),
+ make_view(this->gradd(el_type, _not_ghost), dim),
this->g_c(el_type, _not_ghost))) {
this->computeDissipatedEnergyOnQuad(std::get<1>(tuple), std::get<2>(tuple),
std::get<3>(tuple), std::get<0>(tuple),
std::get<4>(tuple));
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::computeDissipatedEnergyByElement(
+template <Int dim>
+void PhaseFieldLinear<dim>::computeDissipatedEnergyByElement(
ElementType type, Idx index, Vector<Real> & edis_on_quad_points) {
- auto gradd_it = this->gradd(type).begin(spatial_dimension);
- auto gradd_end = this->gradd(type).begin(spatial_dimension);
+ auto gradd_it = this->gradd(type).begin(dim);
+ auto gradd_end = this->gradd(type).begin(dim);
auto damage_it = this->damage_on_qpoints(type).begin();
auto damage_prev_it = this->damage_on_qpoints.previous(type).begin();
auto g_c_it = this->g_c(type).begin();
+ auto & fem = this->getFEEngine();
UInt nb_quadrature_points = fem.getNbIntegrationPoints(type);
gradd_it += index * nb_quadrature_points;
gradd_end += (index + 1) * nb_quadrature_points;
damage_it += index * nb_quadrature_points;
damage_prev_it += index * nb_quadrature_points;
g_c_it += index * nb_quadrature_points;
Real * edis_quad = edis_on_quad_points.data();
for (; gradd_it != gradd_end; ++gradd_it, ++damage_it, ++edis_quad) {
this->computeDissipatedEnergyOnQuad(*damage_it, *damage_prev_it, *gradd_it,
*edis_quad, *g_c_it);
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::computeDissipatedEnergyByElement(
+template <Int dim>
+void PhaseFieldLinear<dim>::computeDissipatedEnergyByElement(
const Element & element, Vector<Real> & edis_on_quad_points) {
computeDissipatedEnergyByElement(element.type, element.element,
edis_on_quad_points);
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldLinear::afterSolveStep() {
+template <Int dim> void PhaseFieldLinear<dim>::afterSolveStep() {
// clamp negative damage to 0
- for (auto & dam : this->model.getDamage()) {
+ for (auto & dam : this->getHandler().getDamage()) {
dam = std::max(Real(0.), dam);
}
}
-INSTANTIATE_PHASEFIELD(linear, PhaseFieldLinear);
+/* -------------------------------------------------------------------------- */
+template class PhaseFieldLinear<1>;
+template class PhaseFieldLinear<2>;
+template class PhaseFieldLinear<3>;
+
+const bool phase_field_linear_is_allocated [[maybe_unused]] =
+ instantiatePhaseField<PhaseFieldLinear>("linear");
} // namespace akantu
diff --git a/src/model/phase_field/phasefields/phasefield_linear.hh b/src/model/phase_field/phasefields/phasefield_linear.hh
index ea0f99506..1cda89da0 100644
--- a/src/model/phase_field/phasefields/phasefield_linear.hh
+++ b/src/model/phase_field/phasefields/phasefield_linear.hh
@@ -1,82 +1,82 @@
/* -------------------------------------------------------------------------- */
#include "phasefield.hh"
/* -------------------------------------------------------------------------- */
#ifndef __AKANTU_PHASEFIELD_LINEAR_HH__
#define __AKANTU_PHASEFIELD_LINEAR_HH__
namespace akantu {
-class PhaseFieldLinear : public PhaseField {
+
+template <Int dim> class PhaseFieldLinear : public PhaseField {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PhaseFieldLinear(PhaseFieldModel & model, const ID & id = "");
~PhaseFieldLinear() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// compute the dissiapted energy
void computeDissipatedEnergy(ElementType el_type) override;
void
computeDissipatedEnergyByElement(const Element & element,
Vector<Real> & edis_on_quad_points) override;
void afterSolveStep() override;
protected:
void
computeDissipatedEnergyByElement(ElementType type, Idx index,
Vector<Real> & edis_on_quad_points) override;
void computePhiOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/);
void computePhiIsotropicOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/);
void computeDrivingForce(ElementType /*el_type*/,
GhostType /*ghost_type*/) override;
inline void computeDrivingForceOnQuad(const Real & /*phi_quad*/,
Real & /*driving_force_quad*/,
const Real & /*g_c_quad*/);
inline void computeDamageEnergyDensityOnQuad(const Real & /*phi_quad*/,
- Real & /*dam_energy_quad*/,
- const Real & /*g_c_quad*/);
+ Real & /*dam_energy_quad*/);
inline void
computeDissipatedEnergyOnQuad(const Real & /*dam_quad*/,
const Real & /*dam_prev_quad*/,
const Vector<Real> & /*grad_d_quad */,
Real & /*energy*/, Real & /*g_c_quad*/);
public:
void updateInternalParameters() override;
void initPhaseField() override;
private:
// irreversibility tolerance
Real tol_ir;
// penalization parameter
Real gamma;
// dimension to consider in deviatoric split
- Int dim;
+ Int dev_dim;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "phasefield_linear_inline_impl.hh"
#endif
diff --git a/src/model/phase_field/phasefields/phasefield_linear_inline_impl.hh b/src/model/phase_field/phasefields/phasefield_linear_inline_impl.hh
index 75befa61d..7db2d57e5 100644
--- a/src/model/phase_field/phasefields/phasefield_linear_inline_impl.hh
+++ b/src/model/phase_field/phasefields/phasefield_linear_inline_impl.hh
@@ -1,62 +1,67 @@
#include "phasefield_linear.hh"
namespace akantu {
-inline void PhaseFieldLinear::computeDissipatedEnergyOnQuad(
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+inline void PhaseFieldLinear<dim>::computeDissipatedEnergyOnQuad(
const Real & dam, const Real & dam_prev, const Vector<Real> & grad_d,
Real & edis, Real & g_c_quad) {
edis = 0.;
- for (auto i : arange(spatial_dimension)) {
+ for (auto i : arange(dim)) {
edis += 3. / 8 * g_c_quad * this->l0 * grad_d[i] * grad_d[i];
}
edis += 3 * g_c_quad * dam * dam / (8 * this->l0);
Real damage_penalized = std::min(0., dam - dam_prev);
edis += 0.5 * this->gamma * damage_penalized * damage_penalized;
}
/* -------------------------------------------------------------------------- */
-inline void PhaseFieldLinear::computeDrivingForceOnQuad(
+template <Int dim>
+inline void PhaseFieldLinear<dim>::computeDrivingForceOnQuad(
const Real & phi_quad, Real & driving_force_quad, const Real & g_c_quad) {
driving_force_quad = phi_quad - 3 * g_c_quad / (16 * this->l0);
}
/* -------------------------------------------------------------------------- */
-inline void PhaseFieldLinear::computeDamageEnergyDensityOnQuad(
- const Real & phi_quad, Real & dam_energy_quad, const Real & g_c_quad) {
+template <Int dim>
+inline void PhaseFieldLinear<dim>::computeDamageEnergyDensityOnQuad(
+ const Real & phi_quad, Real & dam_energy_quad) {
dam_energy_quad = 2 * phi_quad;
}
/* -------------------------------------------------------------------------- */
-inline void PhaseFieldLinear::computePhiOnQuad(const Matrix<Real> & strain_quad,
- Real & phi_quad) {
+template <Int dim>
+inline void
+PhaseFieldLinear<dim>::computePhiOnQuad(const Matrix<Real> & strain_quad,
+ Real & phi_quad) {
Real trace = strain_quad.trace();
Real trace_plus = std::max(Real(0.), trace);
- Matrix<Real> strain_dev(dim, dim);
- Matrix<Real> strain_tmp = Matrix<Real>::Zero(dim, dim);
- strain_tmp.topLeftCorner(spatial_dimension, spatial_dimension) = strain_quad;
+ Matrix<Real> strain_dev = Matrix<Real>::Zero(dev_dim, dev_dim);
+ Matrix<Real> strain_tmp = Matrix<Real>::Zero(dev_dim, dev_dim);
+ strain_tmp.topLeftCorner(dim, dim) = strain_quad;
strain_dev = strain_tmp -
- trace / Real(dim) *
- Matrix<Real>::Identity(dim, dim);
+ trace / Real(dev_dim) * Matrix<Real>::Identity(dev_dim, dev_dim);
- Real kpa = this->lambda + 2. * this->mu / Real(dim);
+ Real kpa = this->lambda + 2. * this->mu / Real(dev_dim);
phi_quad = 0.5 * kpa * trace_plus * trace_plus +
this->mu * strain_dev.doubleDot(strain_dev);
}
/* -------------------------------------------------------------------------- */
-inline void
-PhaseFieldLinear::computePhiIsotropicOnQuad(const Matrix<Real> & strain_quad,
- Real & phi_quad) {
+template <Int dim>
+inline void PhaseFieldLinear<dim>::computePhiIsotropicOnQuad(
+ const Matrix<Real> & strain_quad, Real & phi_quad) {
Real trace = strain_quad.trace();
phi_quad = 0.5 * this->lambda * trace * trace +
this->mu * strain_quad.doubleDot(strain_quad);
}
} // namespace akantu
diff --git a/src/model/phase_field/phasefields/phasefield_quadratic.cc b/src/model/phase_field/phasefields/phasefield_quadratic.cc
index 6dd647265..22f474c02 100644
--- a/src/model/phase_field/phasefields/phasefield_quadratic.cc
+++ b/src/model/phase_field/phasefields/phasefield_quadratic.cc
@@ -1,180 +1,193 @@
/**
* @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_quadratic.hh"
#include "aka_common.hh"
#include <algorithm>
#include <cmath>
#include <iostream>
#include <tuple>
namespace akantu {
/* -------------------------------------------------------------------------- */
-PhaseFieldQuadratic::PhaseFieldQuadratic(PhaseFieldModel & model, const ID & id)
+template <Int dim>
+PhaseFieldQuadratic<dim>::PhaseFieldQuadratic(PhaseFieldModel & model,
+ const ID & id)
: PhaseField(model, id) {
registerParam("irreversibility_tol", tol_ir, Real(1e-2),
_pat_parsable | _pat_readable, "Irreversibility tolerance");
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldQuadratic::initPhaseField() {
+template <Int dim> void PhaseFieldQuadratic<dim>::initPhaseField() {
PhaseField::initPhaseField();
this->gamma = Real(this->g_c) / this->l0 * (1. / (tol_ir * tol_ir) - 1.);
+
+ this->dev_dim = dim;
+ if (dim == 2 && !this->plane_stress) {
+ this->dev_dim = 3;
+ }
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldQuadratic::updateInternalParameters() {
+template <Int dim> void PhaseFieldQuadratic<dim>::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))) {
+ for (const auto & type : getElementFilter().elementTypes(dim, _not_ghost)) {
+ for (auto && tuple :
+ zip(make_view(this->damage_energy(type, _not_ghost), dim, dim),
+ this->g_c(type, _not_ghost))) {
Matrix<Real> d =
- Matrix<Real>::Identity(spatial_dimension, spatial_dimension) *
- std::get<1>(tuple) * this->l0;
+ Matrix<Real>::Identity(dim, dim) * std::get<1>(tuple) * this->l0;
std::get<0>(tuple) = d;
}
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldQuadratic::computeDrivingForce(ElementType el_type,
- GhostType ghost_type) {
+template <Int dim>
+void PhaseFieldQuadratic<dim>::computeDrivingForce(ElementType el_type,
+ GhostType ghost_type) {
if (this->isotropic) {
- for (auto && tuple : zip(this->phi(el_type, ghost_type),
- make_view(this->strain(el_type, ghost_type),
- spatial_dimension, spatial_dimension))) {
+ for (auto && tuple :
+ zip(this->phi(el_type, ghost_type),
+ make_view(this->strain(el_type, ghost_type), dim, dim))) {
auto & phi_quad = std::get<0>(tuple);
auto & strain = std::get<1>(tuple);
computePhiIsotropicOnQuad(strain, phi_quad);
}
} else {
- for (auto && tuple : zip(this->phi(el_type, ghost_type),
- make_view(this->strain(el_type, ghost_type),
- spatial_dimension, spatial_dimension))) {
+ for (auto && tuple :
+ zip(this->phi(el_type, ghost_type),
+ make_view(this->strain(el_type, ghost_type), dim, dim))) {
auto & phi_quad = std::get<0>(tuple);
auto & strain = std::get<1>(tuple);
computePhiOnQuad(strain, phi_quad);
}
}
for (auto && tuple :
zip(this->phi(el_type, ghost_type),
this->driving_force(el_type, ghost_type),
this->damage_energy_density(el_type, ghost_type),
this->damage_on_qpoints(el_type, _not_ghost),
- make_view(this->driving_energy(el_type, ghost_type),
- spatial_dimension),
- make_view(this->damage_energy(el_type, ghost_type),
- spatial_dimension, spatial_dimension),
- make_view(this->gradd(el_type, ghost_type), spatial_dimension),
+ make_view(this->driving_energy(el_type, ghost_type), dim),
+ make_view(this->damage_energy(el_type, ghost_type), dim, dim),
+ make_view(this->gradd(el_type, ghost_type), dim),
this->g_c(el_type, ghost_type),
this->damage_on_qpoints.previous(el_type, ghost_type))) {
auto & phi_quad = std::get<0>(tuple);
auto & driving_force_quad = std::get<1>(tuple);
auto & dam_energy_density_quad = std::get<2>(tuple);
auto & dam_on_quad = std::get<3>(tuple);
auto & driving_energy_quad = std::get<4>(tuple);
auto & damage_energy_quad = std::get<5>(tuple);
auto & gradd_quad = std::get<6>(tuple);
auto & g_c_quad = std::get<7>(tuple);
auto & dam_prev_quad = std::get<8>(tuple);
computeDamageEnergyDensityOnQuad(phi_quad, dam_energy_density_quad,
g_c_quad);
Real penalization =
this->gamma * std::min(Real(0.), dam_on_quad - dam_prev_quad);
driving_force_quad =
dam_on_quad * dam_energy_density_quad - 2 * phi_quad + penalization;
driving_energy_quad = damage_energy_quad * gradd_quad;
dam_energy_density_quad += this->gamma * (dam_on_quad < dam_prev_quad);
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldQuadratic::computeDissipatedEnergy(ElementType el_type) {
+template <Int dim>
+void PhaseFieldQuadratic<dim>::computeDissipatedEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
- for (auto && tuple :
- zip(this->dissipated_energy(el_type, _not_ghost),
- this->damage_on_qpoints(el_type, _not_ghost),
- make_view(this->gradd(el_type, _not_ghost), spatial_dimension),
- this->g_c(el_type, _not_ghost))) {
+ for (auto && tuple : zip(this->dissipated_energy(el_type, _not_ghost),
+ this->damage_on_qpoints(el_type, _not_ghost),
+ make_view(this->gradd(el_type, _not_ghost), dim),
+ this->g_c(el_type, _not_ghost))) {
this->computeDissipatedEnergyOnQuad(std::get<1>(tuple), std::get<2>(tuple),
std::get<0>(tuple), std::get<3>(tuple));
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldQuadratic::computeDissipatedEnergyByElement(
+template <Int dim>
+void PhaseFieldQuadratic<dim>::computeDissipatedEnergyByElement(
ElementType type, Idx index, Vector<Real> & edis_on_quad_points) {
- auto gradd_it = this->gradd(type).begin(spatial_dimension);
- auto gradd_end = this->gradd(type).begin(spatial_dimension);
+ auto gradd_it = this->gradd(type).begin(dim);
+ auto gradd_end = this->gradd(type).begin(dim);
auto damage_it = this->damage_on_qpoints(type).begin();
auto g_c_it = this->g_c(type).begin();
+ auto & fem = this->getFEEngine();
UInt nb_quadrature_points = fem.getNbIntegrationPoints(type);
gradd_it += index * nb_quadrature_points;
gradd_end += (index + 1) * nb_quadrature_points;
damage_it += index * nb_quadrature_points;
g_c_it += index * nb_quadrature_points;
Real * edis_quad = edis_on_quad_points.data();
for (; gradd_it != gradd_end; ++gradd_it, ++damage_it, ++edis_quad) {
this->computeDissipatedEnergyOnQuad(*damage_it, *gradd_it, *edis_quad,
*g_c_it);
}
}
/* -------------------------------------------------------------------------- */
-void PhaseFieldQuadratic::computeDissipatedEnergyByElement(
+template <Int dim>
+void PhaseFieldQuadratic<dim>::computeDissipatedEnergyByElement(
const Element & element, Vector<Real> & edis_on_quad_points) {
computeDissipatedEnergyByElement(element.type, element.element,
edis_on_quad_points);
}
-INSTANTIATE_PHASEFIELD(quadratic, PhaseFieldQuadratic);
+/* -------------------------------------------------------------------------- */
+template class PhaseFieldQuadratic<1>;
+template class PhaseFieldQuadratic<2>;
+template class PhaseFieldQuadratic<3>;
+
+const bool phase_field_quadratic_is_allocated [[maybe_unused]] =
+ instantiatePhaseField<PhaseFieldQuadratic>("quadratic");
} // namespace akantu
diff --git a/src/model/phase_field/phasefields/phasefield_quadratic.hh b/src/model/phase_field/phasefields/phasefield_quadratic.hh
index 197ef018d..dde650279 100644
--- a/src/model/phase_field/phasefields/phasefield_quadratic.hh
+++ b/src/model/phase_field/phasefields/phasefield_quadratic.hh
@@ -1,106 +1,110 @@
/**
* @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_QUADRATIC_HH__
#define __AKANTU_PHASEFIELD_QUADRATIC_HH__
namespace akantu {
-class PhaseFieldQuadratic : public PhaseField {
+
+template<Int dim> class PhaseFieldQuadratic : public PhaseField {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
PhaseFieldQuadratic(PhaseFieldModel & model, const ID & id = "");
~PhaseFieldQuadratic() override = default;
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
/// compute the dissiapted energy
void computeDissipatedEnergy(ElementType el_type) override;
void
computeDissipatedEnergyByElement(const Element & element,
Vector<Real> & edis_on_quad_points) override;
protected:
void
computeDissipatedEnergyByElement(ElementType type, Idx index,
Vector<Real> & edis_on_quad_points) override;
void computePhiOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/);
void computePhiIsotropicOnQuad(const Matrix<Real> & /*strain_quad*/,
Real & /*phi_quad*/);
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*/);
inline void
computeDissipatedEnergyOnQuad(const Real & /*dam_quad*/,
const Vector<Real> & /*grad_d_quad */,
Real & /*energy*/, Real & /*g_c_quad*/);
public:
void updateInternalParameters() override;
void initPhaseField() override;
private:
// irreversibility tolerance
Real tol_ir;
// penalization parameter
Real gamma;
+
+ // dimension to consider in deviatoric split
+ Int dev_dim;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
#include "phasefield_quadratic_inline_impl.hh"
#endif
diff --git a/src/model/phase_field/phasefields/phasefield_quadratic_inline_impl.hh b/src/model/phase_field/phasefields/phasefield_quadratic_inline_impl.hh
index 7cb4a4421..0cd116bdd 100644
--- a/src/model/phase_field/phasefields/phasefield_quadratic_inline_impl.hh
+++ b/src/model/phase_field/phasefields/phasefield_quadratic_inline_impl.hh
@@ -1,52 +1,59 @@
#include "phasefield_quadratic.hh"
#include <algorithm>
namespace akantu {
-inline void PhaseFieldQuadratic::computeDissipatedEnergyOnQuad(
+/* -------------------------------------------------------------------------- */
+template <Int dim>
+inline void PhaseFieldQuadratic<dim>::computeDissipatedEnergyOnQuad(
const Real & dam, const Vector<Real> & grad_d, Real & edis,
Real & g_c_quad) {
edis = 0.;
- for (auto i : arange(spatial_dimension)) {
+ for (auto i : arange(dim)) {
edis += 0.5 * g_c_quad * this->l0 * grad_d[i] * grad_d[i];
}
edis += g_c_quad * dam * dam / (2. * this->l0);
}
/* -------------------------------------------------------------------------- */
-inline void PhaseFieldQuadratic::computeDamageEnergyDensityOnQuad(
+template <Int dim>
+inline void PhaseFieldQuadratic<dim>::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;
}
/* -------------------------------------------------------------------------- */
+template <Int dim>
inline void
-PhaseFieldQuadratic::computePhiOnQuad(const Matrix<Real> & strain_quad,
+PhaseFieldQuadratic<dim>::computePhiOnQuad(const Matrix<Real> & strain_quad,
Real & phi_quad) {
Real trace = strain_quad.trace();
Real trace_plus = std::max(Real(0.), trace);
- Matrix<Real> strain_dev(spatial_dimension, spatial_dimension);
- strain_dev = strain_quad -
- trace / Real(spatial_dimension) *
- Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
+ Matrix<Real> strain_dev = Matrix<Real>::Zero(dev_dim, dev_dim);
+ Matrix<Real> strain_tmp = Matrix<Real>::Zero(dev_dim, dev_dim);
+ strain_tmp.topLeftCorner(dim, dim) = strain_quad;
+
+ strain_dev = strain_tmp -
+ trace / Real(dev_dim) * Matrix<Real>::Identity(dev_dim, dev_dim);
- Real kpa = this->lambda + 2. * this->mu / Real(spatial_dimension);
+ Real kpa = this->lambda + 2. * this->mu / Real(dev_dim);
phi_quad = 0.5 * kpa * trace_plus * trace_plus +
this->mu * strain_dev.doubleDot(strain_dev);
}
/* -------------------------------------------------------------------------- */
+template <Int dim>
inline void
-PhaseFieldQuadratic::computePhiIsotropicOnQuad(const Matrix<Real> & strain_quad,
+PhaseFieldQuadratic<dim>::computePhiIsotropicOnQuad(const Matrix<Real> & strain_quad,
Real & phi_quad) {
Real trace = strain_quad.trace();
phi_quad = 0.5 * this->lambda * trace * trace +
this->mu * strain_quad.doubleDot(strain_quad);
}
} // namespace akantu
diff --git a/src/model/solid_mechanics/material.cc b/src/model/solid_mechanics/material.cc
index ba4e2be2e..5fd5737aa 100644
--- a/src/model/solid_mechanics/material.cc
+++ b/src/model/solid_mechanics/material.cc
@@ -1,1130 +1,831 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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),
+Material::Material(SolidMechanicsModel & model, const ID & id,
+ const ID & fe_engine_id)
+ : Parent(model, id, model.getSpatialDimension(), _ek_regular, fe_engine_id),
+ stress(registerInternal("stress", spatial_dimension * spatial_dimension,
+ fe_engine_id)),
+ eigengradu(registerInternal(
+ "eigen_grad_u", spatial_dimension * spatial_dimension, fe_engine_id)),
+ gradu(registerInternal("grad_u", spatial_dimension * spatial_dimension,
+ fe_engine_id)),
+ potential_energy(registerInternal("potential_energy", 1, fe_engine_id)),
interpolation_inverse_coordinates("interpolation inverse coordinates",
- *this),
- interpolation_points_matrices("interpolation points matrices", *this),
+ id),
+ interpolation_points_matrices("interpolation points matrices", id),
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();
-}
-
-/* -------------------------------------------------------------------------- */
-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) {
- eigen_grad_u.fill(0.);
-
- element_filter.initialize(mesh, _spatial_dimension = spatial_dimension,
- _element_kind = _ek_regular);
-
- this->initialize();
-}
-
-/* -------------------------------------------------------------------------- */
-Material::~Material() = default;
-
-/* -------------------------------------------------------------------------- */
-void Material::initialize() {
+ eigen_grad_u.setZero();
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");
+ registerParam("eigen_grad_u", eigen_grad_u, _pat_parsable, "EigenGradU");
- /// 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);
+ this->getModel().registerEventHandler(*this);
}
/* -------------------------------------------------------------------------- */
void Material::initMaterial() {
AKANTU_DEBUG_IN();
if (finite_deformation) {
- this->piola_kirchhoff_2.initialize(spatial_dimension * spatial_dimension);
- this->piola_kirchhoff_2.initializeHistory();
- this->green_strain.initialize(spatial_dimension * spatial_dimension);
+ this->registerInternal("piola_kirchhoff_2",
+ spatial_dimension * spatial_dimension);
+ this->piola_kirchhoff_2 = this->getSharedPtrInternal("piola_kirchhoff_2");
+ this->piola_kirchhoff_2->initializeHistory();
+ this->registerInternal("green_strain",
+ spatial_dimension * spatial_dimension);
+ this->green_strain = this->getSharedPtrInternal("green_strain");
}
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();
-
+ Parent::initConstitutiveLaw();
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();
+void Material::updateInternalParameters() {
+ auto dim = getModel().getSpatialDimension();
+ for (const auto & type :
+ getElementFilter().elementTypes(_element_kind = _ek_regular)) {
+ for (auto eigen_gradu : make_view(eigengradu(type), dim, dim)) {
+ eigen_gradu = eigen_grad_u;
}
}
- AKANTU_DEBUG_OUT();
+ Parent::updateInternalParameters();
}
/* -------------------------------------------------------------------------- */
/**
* 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();
- Int spatial_dimension = model.getSpatialDimension();
+ Int spatial_dimension = getModel().getSpatialDimension();
tuple_dispatch<AllSpatialDimensions>(
[&](auto && _) {
constexpr auto dim = aka::decay_v<decltype(_)>;
for (auto && type :
- element_filter.elementTypes(spatial_dimension, ghost_type)) {
+ getElementFilter().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();
- auto spatial_dimension = model.getSpatialDimension();
-
+ auto spatial_dimension = getModel().getSpatialDimension();
+ auto & fem = getFEEngine();
for (const auto & type :
- element_filter.elementTypes(spatial_dimension, ghost_type)) {
- auto & elem_filter = element_filter(type, ghost_type);
+ getElementFilter().elementTypes(spatial_dimension, ghost_type)) {
+ auto & elem_filter = getElementFilter(type, ghost_type);
if (elem_filter.empty()) {
continue;
}
auto & gradu_vect = gradu(type, ghost_type);
/// compute @f$\nabla u@f$
- fem.gradientOnIntegrationPoints(model.getDisplacement(), gradu_vect,
+ fem.gradientOnIntegrationPoints(getModel().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)) {
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, ghost_type)) {
tuple_dispatch<AllSpatialDimensions>(
[&](auto && _) {
constexpr auto dim = aka::decay_v<decltype(_)>;
this->StoCauchy<dim>(type, ghost_type);
},
spatial_dimension);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void Material::StoCauchy(ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
- for (auto && data :
+ for (auto && [grad_u, piola, sigma] :
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->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);
-
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 auto & displacement = model.getDisplacement();
-
+ const auto & displacement = getModel().getDisplacement();
+ auto & fem = getFEEngine();
// resizeInternalArray(gradu);
- auto spatial_dimension = model.getSpatialDimension();
+ auto spatial_dimension = getModel().getSpatialDimension();
- for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
- auto & elem_filter = element_filter(type, ghost_type);
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, ghost_type)) {
+ auto & elem_filter = getElementFilter(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();
- auto spatial_dimension = model.getSpatialDimension();
+ auto spatial_dimension = getModel().getSpatialDimension();
tuple_dispatch<AllSpatialDimensions>(
[&](auto && _) {
constexpr auto dim = aka::decay_v<decltype(_)>;
for (auto type :
- element_filter.elementTypes(spatial_dimension, ghost_type)) {
+ getElementFilter().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 <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();
- const auto & elem_filter = element_filter(type, ghost_type);
+ const auto & elem_filter = getElementFilter(type, ghost_type);
if (elem_filter.empty()) {
AKANTU_DEBUG_OUT();
return;
}
+ auto & fem = getFEEngine();
auto & gradu_vect = gradu(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,
+ fem.gradientOnIntegrationPoints(getModel().getDisplacement(), gradu_vect, dim,
type, ghost_type, elem_filter);
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$
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");
fem.computeBtDB(*tangent_stiffness_matrix, *bt_d_b, 4, type, ghost_type,
elem_filter);
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
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);
- model.getDOFManager().assembleElementalMatricesToMatrix(
+ getModel().getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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);
}
/* -------------------------------------------------------------------------- */
template <Int dim, ElementType type>
void Material::assembleStiffnessMatrixNL(GhostType ghost_type) {
AKANTU_DEBUG_IN();
+ auto & fem = getFEEngine();
const auto & shapes_derivatives = fem.getShapesDerivatives(type, ghost_type);
- const auto & elem_filter = element_filter(type, ghost_type);
+ const auto & elem_filter = getElementFilter(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 = 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$
constexpr auto bt_s_b_size = dim * nb_nodes_per_element;
constexpr auto piola_matrix_size = getCauchyStressMatrixSize(dim);
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");
Matrix<Real, piola_matrix_size, bt_s_b_size> B;
Matrix<Real, piola_matrix_size, piola_matrix_size> S;
- for (auto && data :
+ for (auto && [Bt_S_B, Piola_kirchhoff_matrix, shapes_derivatives] :
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, 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, B,
nb_nodes_per_element);
Bt_S_B = B.transpose() * S * B;
}
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
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);
- model.getDOFManager().assembleElementalMatricesToMatrix(
+ getModel().getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim, ElementType type>
void Material::assembleStiffnessMatrixL2(GhostType ghost_type) {
AKANTU_DEBUG_IN();
+ auto & fem = getFEEngine();
const auto & shapes_derivatives = fem.getShapesDerivatives(type, ghost_type);
- auto & elem_filter = element_filter(type, ghost_type);
+ auto & elem_filter = getElementFilter(type, ghost_type);
auto & gradu_vect = gradu(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,
+ fem.gradientOnIntegrationPoints(getModel().getDisplacement(), gradu_vect, dim,
type, ghost_type, elem_filter);
constexpr auto tangent_size = getTangentStiffnessVoigtSize(dim);
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 = 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$
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 :
+ for (auto && [Bt_D_B, grad_u, D, shapes_derivative] :
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_derivative, B,
nb_nodes_per_element);
VoigtHelper<dim>::transferBMatrixToBL2(shapes_derivative, grad_u, B2,
nb_nodes_per_element);
B += B2;
Bt_D_B = B.transpose() * D * B;
}
/// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$
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);
- model.getDOFManager().assembleElementalMatricesToMatrix(
+ getModel().getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _symmetric, elem_filter);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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);
}
/* -------------------------------------------------------------------------- */
template <Int dim, ElementType type>
void Material::assembleInternalForces(GhostType ghost_type) {
- auto & internal_force = model.getInternalForce();
+ auto & internal_force = getModel().getInternalForce();
// Mesh & mesh = fem.getMesh();
- auto && elem_filter = element_filter(type, ghost_type);
+ auto && elem_filter = getElementFilter(type, ghost_type);
auto nb_element = elem_filter.size();
if (nb_element == 0) {
return;
}
- const Array<Real> & shapes_derivatives =
- fem.getShapesDerivatives(type, ghost_type);
+ auto && fem = this->getFEEngine();
+ const auto & 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);
+ auto size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
+ auto 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");
+ auto sigma_dphi_dx = std::make_unique<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");
+ auto int_sigma_dphi_dx = std::make_unique<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(
+ getModel().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);
}
/* -------------------------------------------------------------------------- */
template <Int dim, ElementType type>
void Material::assembleInternalForcesFiniteDeformation(GhostType ghost_type) {
AKANTU_DEBUG_IN();
- auto & internal_force = model.getInternalForce();
+ auto & fem = getFEEngine();
+ auto & internal_force = getModel().getInternalForce();
auto & mesh = fem.getMesh();
const auto & shapes_derivatives = fem.getShapesDerivatives(type, ghost_type);
- auto & elem_filter = element_filter(type, ghost_type);
- if (elem_filter.size() == 0)
+ auto & elem_filter = getElementFilter(type, ghost_type);
+ if (elem_filter.empty()) {
return;
+ }
auto size_of_shapes_derivatives = shapes_derivatives.getNbComponent();
auto nb_element = elem_filter.size();
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;
auto nb_quadrature_points = fem.getNbIntegrationPoints(type, ghost_type);
auto shapesd_filtered = std::make_unique<Array<Real>>(
nb_element, size_of_shapes_derivatives, "filtered shapesd");
FEEngine::filterElementalData(mesh, shapes_derivatives, *shapesd_filtered,
type, ghost_type, elem_filter);
// Set stress vectors
auto bt_s = std::make_unique<Array<Real>>(nb_element * nb_quadrature_points,
bt_s_size, "B^t*S");
Matrix<Real, stress_size, bt_s_size> B_tensor;
Matrix<Real, stress_size, bt_s_size> B2_tensor;
- for (auto && data :
+ for (auto && [grad_u, S, r, shapes_derivative] :
zip(make_view<dim, dim>(this->gradu(type, ghost_type)),
- make_view<dim, dim>(this->piola_kirchhoff_2(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);
-
VoigtHelper<dim>::transferBMatrixToSymVoigtBMatrix(
shapes_derivative, B_tensor, nb_nodes_per_element);
VoigtHelper<dim>::transferBMatrixToBL2(shapes_derivative, grad_u, B2_tensor,
nb_nodes_per_element);
B_tensor += B2_tensor;
auto && S_voight = Material::stressToVoigt<dim>(S);
r = B_tensor.transpose() * S_voight;
}
/// 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);
- model.getDOFManager().assembleElementalArrayLocalArray(
+ getModel().getDOFManager().assembleElementalArrayLocalArray(
*r_e, internal_force, type, ghost_type, -1., elem_filter);
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::computePotentialEnergyByElements() {
AKANTU_DEBUG_IN();
- for (auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, _not_ghost)) {
computePotentialEnergy(type);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
-void Material::computePotentialEnergy(ElementType) { AKANTU_TO_IMPLEMENT(); }
+void Material::computePotentialEnergy(ElementType /*type*/) {
+ AKANTU_TO_IMPLEMENT();
+}
/* -------------------------------------------------------------------------- */
Real Material::getPotentialEnergy() {
AKANTU_DEBUG_IN();
Real epot = 0.;
-
+ auto & fem = getFEEngine();
computePotentialEnergyByElements();
/// integrate the potential energy for each type of elements
- for (auto type : element_filter.elementTypes(spatial_dimension, _not_ghost)) {
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, _not_ghost)) {
epot += fem.integrate(potential_energy(type, _not_ghost), type, _not_ghost,
- element_filter(type, _not_ghost));
+ getElementFilter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return epot;
}
/* -------------------------------------------------------------------------- */
Real Material::getPotentialEnergy(ElementType type, Int index) {
return getPotentialEnergy({type, index, _not_ghost});
}
/* -------------------------------------------------------------------------- */
Real Material::getPotentialEnergy(const Element & element) {
AKANTU_DEBUG_IN();
-
+ auto & fem = getFEEngine();
Vector<Real> epot_on_quad_points(fem.getNbIntegrationPoints(element.type));
- computePotentialEnergyByElement(element, epot_on_quad_points);
auto epot = fem.integrate(epot_on_quad_points,
{element.type,
- element_filter(element.type)(element.element),
+ getElementFilter(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,
const Element & element) {
AKANTU_DEBUG_IN();
if (energy_id == "potential") {
return getPotentialEnergy(element);
}
AKANTU_DEBUG_OUT();
return 0.;
}
/* -------------------------------------------------------------------------- */
void Material::initElementalFieldInterpolation(
const ElementTypeMapArray<Real> & interpolation_points_coordinates) {
AKANTU_DEBUG_IN();
-
- this->fem.initElementalFieldInterpolationFromIntegrationPoints(
+ auto & fem = getFEEngine();
+ fem.initElementalFieldInterpolationFromIntegrationPoints(
interpolation_points_coordinates, this->interpolation_points_matrices,
- this->interpolation_inverse_coordinates, &(this->element_filter));
+ this->interpolation_inverse_coordinates, &(this->getElementFilter()));
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void Material::interpolateStress(ElementTypeMapArray<Real> & result,
const GhostType ghost_type) {
- this->fem.interpolateElementalFieldFromIntegrationPoints(
+ auto & fem = getFEEngine();
+ fem.interpolateElementalFieldFromIntegrationPoints(
this->stress, this->interpolation_points_matrices,
this->interpolation_inverse_coordinates, result, ghost_type,
- &(this->element_filter));
+ &(this->getElementFilter()));
}
/* -------------------------------------------------------------------------- */
void Material::interpolateStressOnFacets(
ElementTypeMapArray<Real> & result,
ElementTypeMapArray<Real> & by_elem_result, const GhostType ghost_type) {
interpolateStress(by_elem_result, ghost_type);
auto stress_size = this->stress.getNbComponent();
- const auto & mesh = this->model.getMesh();
+ const auto & mesh = this->getModel().getMesh();
const auto & mesh_facets = mesh.getMeshFacets();
- for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type)) {
+ for (auto type :
+ getElementFilter().elementTypes(spatial_dimension, ghost_type)) {
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);
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{type, 0, ghost_type};
auto && by_elem_res =
make_view(by_elem_result(type, ghost_type), stress_size,
nb_quad_per_facet, nb_facet_per_elem)
.begin();
- for (auto global_el : element_filter(type, ghost_type)) {
+ for (auto global_el : getElementFilter(type, ghost_type)) {
element.element = global_el;
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;
+ Int(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<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<Idx> element_filter_tmp("element_filter_tmp", id);
-
- element_filter_tmp.initialize(mesh, _element_filter = &element_filter,
- _element_kind = _ek_not_defined);
-
- 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_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_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<Idx> & new_numbering,
- [[gnu::unused]] const RemovedElementsEvent & event) {
- auto my_num = model.getInternalIndexFromID(getID());
-
- 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<Idx> elem_filter_tmp;
- UInt ni = 0;
- Element el{type, 0, gt};
-
- for (auto && data : enumerate(elem_filter)) {
- el.element = std::get<1>(data);
- if (std::find(el_begin, el_end, el) == el_end) {
- 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(std::get<0>(data)) = ni;
-
- mat_indexes(new_el) = my_num;
- mat_loc_num(new_el) = ni;
- ++ni;
- } else {
- 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_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(
+ for (const auto & type : getElementFilter().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(
+ for (const auto & type : getElementFilter().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,
const Matrix<Real> & /*point*/,
Matrix<Real> & extrapolated) {
if (this->isInternal<Real>(id, element.kind())) {
auto name = this->getID() + ":" + id;
auto nb_quads =
- this->internal_vectors_real[name]->getFEEngine().getNbIntegrationPoints(
+ this->getInternal<Real>(name).getFEEngine().getNbIntegrationPoints(
element.type, element.ghost_type);
const auto & internal =
this->getArray<Real>(id, element.type, element.ghost_type);
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");
auto && values = internal_it[local_element.element];
- Int index = 0;
+ Idx index = 0;
Vector<Real> tmp(nb_component);
for (Int j = 0; j < values.cols(); ++j) {
tmp = values(j);
if (tmp.norm() > 0) {
index = j;
break;
}
}
for (Int i = 0; i < extrapolated.size(); ++i) {
extrapolated(i) = values(index);
}
} else {
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()) {
+ for (auto && type : getElementFilter().elementTypes(
+ _all_dimensions, _not_ghost, _ek_not_defined)) {
+ if (getElementFilter(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 71494dbf3..d79ac4b7d 100644
--- a/src/model/solid_mechanics/material.hh
+++ b/src/model/solid_mechanics/material.hh
@@ -1,803 +1,625 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "constitutive_law.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, 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,
+class Material : public ConstitutiveLaw<SolidMechanicsModel>,
protected SolidMechanicsModelEventHandler {
+ using Parent = ConstitutiveLaw<SolidMechanicsModel>;
/* ------------------------------------------------------------------------ */
/* 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, Int dim, const Mesh & mesh,
- FEEngine & fe_engine, const ID & id = "");
-
- /// Destructor
- ~Material() override;
-
-protected:
- void initialize();
+ Material(SolidMechanicsModel & model, const ID & id = "material",
+ const ID & fe_engine_id = "");
/* ------------------------------------------------------------------------ */
/* 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
[[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(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() {}
+ /// function called to update the internal parameters when the
+ /// modifiable parameters are modified
+ void updateInternalParameters() override;
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 {
+ [[nodiscard]] 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 {
+ [[nodiscard]] 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 {
+ [[nodiscard]] 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);
+ void initConstitutiveLaw() override { this->initMaterial(); }
/// assemble the residual for this material
virtual void assembleInternalForces(GhostType ghost_type);
- /// save the internals in the previous_stress if needed
- virtual void savePreviousState();
-
- /// 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 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:
/* ------------------------------------------------------------------------ */
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)),
+ zip("grad_u"_n = make_view<dim, dim>(gradu(el_type, ghost_type)),
"previous_sigma"_n =
- make_view<dim, dim>(this->stress.previous(el_type, ghost_type)),
+ make_view<dim, dim>(stress.previous(el_type, ghost_type)),
"previous_grad_u"_n =
- make_view<dim, dim>(this->gradu.previous(el_type, ghost_type)));
+ make_view<dim, dim>(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>(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)));
+ (*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)));
+ "grad_u"_n = make_view<dim, dim>(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 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);
/// 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 <Int dim>
void assembleStiffnessMatrix(ElementType type, GhostType ghost_type);
/// assembling in finite deformation
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 <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 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 <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 <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 <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 <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 <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 <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 <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;
}
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 Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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<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<Idx> & new_numbering,
- const RemovedElementsEvent & event) 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 &)
+ [[nodiscard]] const SolidMechanicsModel & getModel() const {
+ return this->getHandler();
+ }
+ [[nodiscard]] SolidMechanicsModel & getModel() { return this->getHandler(); }
- 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, 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(const Element & element);
[[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);
+ Real getEnergy(const std::string & type) override;
/// return the energy (identified by id) for the provided element
- virtual Real getEnergy(const std::string & energy_id,
- const Element & element);
+ Real getEnergy(const std::string & energy_id,
+ const Element & element) override;
[[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, 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<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<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);
+ AKANTU_GET_MACRO_AUTO(GradU, gradu);
+ AKANTU_GET_MACRO_AUTO(Stress, stress);
+
+ [[nodiscard]] bool isNonLocal() const { return is_non_local; }
+
+ [[nodiscard]] bool isFiniteDeformation() const { return finite_deformation; }
+ [[nodiscard]] bool isInelasticDeformation() const {
+ return inelastic_deformation;
+ }
/// 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 method to retrieve 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<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
- Int spatial_dimension;
-
- /// list of element handled by the material
- ElementTypeMapArray<Idx> element_filter;
-
/// stresses arrays ordered by element types
- InternalField<Real> stress;
+ InternalField<Real> & stress;
/// eigengrad_u arrays ordered by element types
- InternalField<Real> eigengradu;
+ InternalField<Real> & eigengradu;
/// grad_u arrays ordered by element types
- InternalField<Real> gradu;
+ InternalField<Real> & gradu;
/// Green Lagrange strain (Finite deformation)
- InternalField<Real> green_strain;
+ std::shared_ptr<InternalField<Real>> green_strain;
/// Second Piola-Kirchhoff stress tensor arrays ordered by element types
/// (Finite deformation)
- InternalField<Real> piola_kirchhoff_2;
+ std::shared_ptr<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};
+ InternalField<Real> & potential_energy;
/// elemental field interpolation coordinates
- InternalField<Real> interpolation_inverse_coordinates;
+ ElementTypeMapArray<Real> interpolation_inverse_coordinates;
/// elemental field interpolation points
- InternalField<Real> interpolation_points_matrices;
+ ElementTypeMapArray<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;
+ /// tell if using in non local mode or not
+ bool is_non_local{false};
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), \
+ 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]] 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 = \
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]] 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 }
/* -------------------------------------------------------------------------- */
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);
});
}
} // 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 dcef47e53..85632fd1e 100644
--- a/src/model/solid_mechanics/material_inline_impl.hh
+++ b/src/model/solid_mechanics/material_inline_impl.hh
@@ -1,588 +1,222 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_CC__
// #define __AKANTU_MATERIAL_INLINE_IMPL_CC__
namespace akantu {
-/* -------------------------------------------------------------------------- */
-inline auto Material::addElement(ElementType type, Int element,
- GhostType ghost_type) {
- auto & el_filter = this->element_filter(type, ghost_type);
- el_filter.push_back(element);
- return el_filter.size() - 1;
-}
-
-/* -------------------------------------------------------------------------- */
-inline auto Material::addElement(const Element & element) {
- return this->addElement(element.type, element.element, element.ghost_type);
-}
-
/* -------------------------------------------------------------------------- */
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;
}
/* -------------------------------------------------------------------------- */
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 <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);
Matrix<Real, dim, dim> F_S;
F_S = F * S;
- Real constant = J ? 1. / J : 0;
+ Real constant = (J < std::numeric_limits<Real>::epsilon()) ? 0. : 1. / J;
sigma = constant * F_S * F.transpose();
}
/* -------------------------------------------------------------------------- */
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 <typename D1, typename D2>
constexpr inline void Material::rightCauchy(const Eigen::MatrixBase<D1> & F,
Eigen::MatrixBase<D2> & C) {
C = F.transpose() * F;
}
/* -------------------------------------------------------------------------- */
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;
}
/* -------------------------------------------------------------------------- */
template <typename D1, typename D2>
constexpr inline void Material::leftCauchy(const Eigen::MatrixBase<D1> & F,
Eigen::MatrixBase<D2> & B) {
B = F * F.transpose();
}
/* -------------------------------------------------------------------------- */
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 <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 <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 <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 <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;
}
/* -------------------------------------------------------------------------- */
template <typename D1>
inline Real Material::stressToVonMises(const Eigen::MatrixBase<D1> & stress) {
// compute deviatoric stress
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 <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 (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);
}
}
}
}
-/* -------------------------------------------------------------------------- */
-inline Element
-Material::convertToLocalElement(const Element & global_element) const {
- auto ge = global_element.element;
-#ifndef AKANTU_NDEBUG
- auto model_mat_index = this->model.getMaterialByElement(
- global_element.type, global_element.ghost_type)(ge);
-
- 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
- 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 {
- 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();
- auto && nb_quad = fem.getNbIntegrationPoints(global_point.type);
- auto && el =
- this->convertToLocalElement(static_cast<const Element &>(global_point));
- return IntegrationPoint(el, global_point.num_point, nb_quad);
-}
-
-/* -------------------------------------------------------------------------- */
-inline IntegrationPoint
-Material::convertToGlobalPoint(const IntegrationPoint & local_point) const {
- const FEEngine & fem = this->model.getFEEngine();
- 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 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) *
+ spatial_dimension * Int(sizeof(Real)) *
this->getModel().getNbIntegrationPoints(elements);
}
if (tag == SynchronizationTag::_smm_gradu) {
- return spatial_dimension * spatial_dimension * sizeof(Real) *
- this->getModel().getNbIntegrationPoints(elements);
+ return spatial_dimension * spatial_dimension * Int(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);
+ packInternalFieldHelper(*piola_kirchhoff_2, buffer, elements);
+ packInternalFieldHelper(gradu, buffer, elements);
}
- packElementDataHelper(stress, buffer, elements);
+ packInternalFieldHelper(stress, buffer, elements);
}
if (tag == SynchronizationTag::_smm_gradu) {
- packElementDataHelper(gradu, buffer, elements);
+ packInternalFieldHelper(gradu, 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);
+ unpackInternalFieldHelper(*piola_kirchhoff_2, buffer, elements);
+ unpackInternalFieldHelper(gradu, buffer, elements);
}
- unpackElementDataHelper(stress, buffer, elements);
- }
- if (tag == SynchronizationTag::_smm_gradu) {
- unpackElementDataHelper(gradu, 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());
+ unpackInternalFieldHelper(stress, buffer, elements);
}
- 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<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<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<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 auto & fe_engine = internal_field.getFEEngine();
- auto nb_data_per_quad = internal_field.getNbComponent();
- ElementTypeMap<Int> res;
- for (auto ghost_type : ghost_types) {
- 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 auto & internal_field = this->template getInternal<T>(field_id);
-
- 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
- auto nb_element_dst = mesh.getNbElement(type, ghost_type);
- // number of element in the internal field
- // auto nb_element_src = filter.size();
- // number of quadrature points per elem
- auto nb_quad_per_elem = fe_engine.getNbIntegrationPoints(type);
- // number of data per quadrature point
- auto nb_data_per_quad = internal_field.getNbComponent();
-
- 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
- auto nb_data = nb_quad_per_elem * nb_data_per_quad;
-
- 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(const ID & /*int_id*/) const {
- AKANTU_TO_IMPLEMENT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-inline InternalField<T> & Material::getInternal(const ID & /*int_id*/) {
- AKANTU_TO_IMPLEMENT();
-}
-
-/* -------------------------------------------------------------------------- */
-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<Int> &
-Material::getInternal(const ID & int_id) const {
- 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<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 << "]");
+ if (tag == SynchronizationTag::_smm_gradu) {
+ unpackInternalFieldHelper(gradu, buffer, elements);
}
}
} // namespace akantu
-//#endif /* __AKANTU_MATERIAL_INLINE_IMPL_CC__ */
+// #endif /* __AKANTU_MATERIAL_INLINE_IMPL_CC__ */
diff --git a/src/model/solid_mechanics/material_list.hh.in b/src/model/solid_mechanics/material_list.hh.in
deleted file mode 100644
index 31192f229..000000000
--- a/src/model/solid_mechanics/material_list.hh.in
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * @file material_list.hh.in
- *
- * @author Nicolas Richart <nicolas.richart@epfl.ch>
- *
- * @date creation: Wed Sep 01 2010
- * @date last modification: Wed Feb 03 2016
- *
- * @brief List of materials and all includes
- *
- *
- * Copyright (©) 2014-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/>.
- *
- */
-
-/* -------------------------------------------------------------------------- */
-
-#ifndef __AKANTU_MATERIAL_LIST_HH__
-#define __AKANTU_MATERIAL_LIST_HH__
-
-#include "aka_config.hh"
-
-/* -------------------------------------------------------------------------- */
-/* Material includes */
-/* -------------------------------------------------------------------------- */
-@AKANTU_MATERIAL_INCLUDES@
-
-/* -------------------------------------------------------------------------- */
-/* Material list */
-/* -------------------------------------------------------------------------- */
-#define AKANTU_MATERIAL_LIST \
-@AKANTU_MATERIAL_LISTS@
-
-// leave an empty line after the list
-
-#endif /* __AKANTU_MATERIAL_LIST_HH__ */
diff --git a/src/model/solid_mechanics/material_selector.hh b/src/model/solid_mechanics/material_selector.hh
index 9f039b770..8f84737be 100644
--- a/src/model/solid_mechanics/material_selector.hh
+++ b/src/model/solid_mechanics/material_selector.hh
@@ -1,147 +1,43 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
+#include "constitutive_law_selector.hh"
#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(Int fallback_value = 0) : fallback_value(fallback_value){};
- virtual ~MaterialSelector() = default;
- virtual inline Int operator()(const Element & element) {
- if (fallback_selector) {
- return (*fallback_selector)(element);
- }
-
- return fallback_value;
- }
-
- 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 Int getFallbackValue() const { return this->fallback_value; }
-
-protected:
- 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<Idx> & material_index)
- : material_index(material_index) {}
-
- 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 != Int(-1)) {
- return tmp_mat;
- }
- }
-
- return MaterialSelector::operator()(element);
- }
-
-private:
- const ElementTypeMapArray<Idx> & material_index;
-};
-
-/* -------------------------------------------------------------------------- */
-/**
- * Use elemental data to assign materials
- */
+using DefaultMaterialSelector = DefaultConstitutiveLawSelector;
template <typename T>
-class ElementDataMaterialSelector : public MaterialSelector {
-public:
- ElementDataMaterialSelector(const ElementTypeMapArray<T> & element_data,
- const SolidMechanicsModel & model,
- 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 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
- Int first_index;
-};
-
-/* -------------------------------------------------------------------------- */
-/**
- * class to use mesh data information to assign different materials
- * where name is the tag value: tag_0, tag_1
- */
+using ElementDataMaterialSelector =
+ ElementDataConstitutiveLawSelector<T, SolidMechanicsModel>;
template <typename T>
-class MeshDataMaterialSelector : public ElementDataMaterialSelector<T> {
-public:
- MeshDataMaterialSelector(const std::string & name,
- const SolidMechanicsModel & model,
- Int first_index = 1);
-};
-
+using MeshDataMaterialSelector =
+ MeshDataConstitutiveLawSelector<T, SolidMechanicsModel>;
} // 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 2c1da6783..bd5f70652 100644
--- a/src/model/solid_mechanics/material_selector_tmpl.hh
+++ b/src/model/solid_mechanics/material_selector_tmpl.hh
@@ -1,69 +1,28 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 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 Int
-ElementDataMaterialSelector<Int>::operator()(const Element & element) {
- try {
- return this->elementData(element) - first_index;
- } catch (...) {
- return MaterialSelector::operator()(element);
- }
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T>
-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,
- 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/material_core_includes.hh b/src/model/solid_mechanics/materials/material_core_includes.hh
deleted file mode 100644
index 55ec3099f..000000000
--- a/src/model/solid_mechanics/materials/material_core_includes.hh
+++ /dev/null
@@ -1,72 +0,0 @@
-/**
- * Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * 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_CORE_INCLUDES_HH_
-#define AKANTU_MATERIAL_CORE_INCLUDES_HH_
-
-/* -------------------------------------------------------------------------- */
-/* Material list */
-/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_CMAKE_LIST_MATERIALS
-
-// elastic materials
-#include "material_elastic.hh"
-#include "material_elastic_linear_anisotropic.hh"
-#include "material_elastic_orthotropic.hh"
-#include "material_neohookean.hh"
-
-// visco-elastic materials
-#include "material_standard_linear_solid_deviatoric.hh"
-
-// damage laws
-#include "material_marigo.hh"
-#include "material_mazars.hh"
-
-// phasefield laws
-#include "material_phasefield.hh"
-#include "material_phasefield_anisotropic.hh"
-
-// small-deformation plasticity
-#include "material_linear_isotropic_hardening.hh"
-
-// Drucker-Prager plasticity
-#include "material_drucker_prager.hh"
-
-// von-mises plasticity with damage
-#include "material_von_mises_mazars.hh"
-
-#endif
-
-#define AKANTU_CORE_MATERIAL_LIST \
- ((2, (elastic, MaterialElastic)))((2, (neohookean, MaterialNeohookean)))( \
- (2, (elastic_orthotropic, MaterialElasticOrthotropic)))( \
- (2, (elastic_anisotropic, MaterialElasticLinearAnisotropic)))( \
- (2, (sls_deviatoric, MaterialStandardLinearSolidDeviatoric)))( \
- (2, (marigo, MaterialMarigo)))((2, (mazars, MaterialMazars)))( \
- (2, (plastic_linear_isotropic_hardening, \
- MaterialLinearIsotropicHardening)))( \
- (2, (plastic_drucker_prager, MaterialDruckerPrager)))( \
- (2, (plastic_mazars, MaterialVonMisesMazars)))( \
- (2, (phasefield, MaterialPhaseField)))( \
- (2, (phasefield_anisotropic, MaterialPhaseFieldAnisotropic)))
-
-#endif /* AKANTU_MATERIAL_CORE_INCLUDES_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 60b3a04ed..0d90980b7 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,54 +1,55 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
/* -------------------------------------------------------------------------- */
-static bool material_is_alocated_anisotropic_damage [[gnu::unused]] =
- MaterialFactory::getInstance().registerAllocator(
- "anisotropic_damage",
- [](Int dim, const ID & option, SolidMechanicsModel & model,
- const ID & id) -> std::unique_ptr<Material> {
- return tuple_dispatch<AllSpatialDimensions>(
- [&](auto && _) -> std::unique_ptr<Material> {
- constexpr auto dim_ = aka::decay_v<decltype(_)>;
+const bool material_is_alocated_anisotropic_damage
+ [[gnu::unused]] [[maybe_unused]] =
+ MaterialFactory::getInstance().registerAllocator(
+ "anisotropic_damage",
+ [](Int dim, const ID & option, SolidMechanicsModel & model,
+ const ID & id) -> std::unique_ptr<Material> {
+ 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);
- });
+ 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 c612045a0..6bc457683 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,98 +1,97 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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:
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 criteria
+ EquivalentStrain<dim> equivalent_strain_function;
+
+ /// damage evolution
+ DamageThreshold<dim> damage_threshold_function;
+
/// damage internal variable
- InternalField<Real> damage;
+ InternalField<Real> & damage;
/// elastic stress
- InternalField<Real> elastic_stress;
+ InternalField<Real> & elastic_stress;
/// equivalent strain
- InternalField<Real> 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;
+ /// trace of the damage threshold
+ InternalField<Real> & trace_damage;
};
} // 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 e56aa8ced..26c0e1c68 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,366 +1,358 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
+#include "material_anisotropic_damage.hh" // NOLINT(pp_including_mainfile_in_preamble)
/* -------------------------------------------------------------------------- */
#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 <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 <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 <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::pair(trace_plus, trace_minus);
}
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 && [i, eig] : enumerate(A_eigs)) {
A_diag(i, i) = oper(std::max(eig, 0.), i);
}
Matrix<Real, dim, dim> res =
A_directions * A_diag * A_directions.transpose();
return res;
}
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 <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 <Int dim, class D> auto tensorPlus(const Eigen::MatrixBase<D> & A) {
return tensorPlusOp<dim>(A, [](Real x, Real) { return 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 <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) {
+ : Parent<dim>(model, id), equivalent_strain_function(*this),
+ damage_threshold_function(*this),
+ damage(this->registerInternal("damage", dim * dim)),
+ elastic_stress(this->registerInternal("elastic_stress", dim * dim)),
+ equivalent_strain(this->registerInternal("equivalent_strain", 1)),
+ trace_damage(this->registerInternal("trace_damage", 1)) {
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 <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(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
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 && [Tr_sigma_plus, Tr_sigma_minus] = tensorPlusTrace<dim>(sigma_el);
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 <Int dim, template <Int> class EquivalentStrain,
template <Int> class DamageThreshold, template <Int> class Parent>
template <class Args>
void MaterialAnisotropicDamage<dim, EquivalentStrain, DamageThreshold,
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];
Matrix<Real, dim, dim> Dtmp;
- Real TrD_n_1_tmp;
+ Real TrD_n_1_tmp{0.};
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);
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);
}
/* -------------------------------------------------------------------------- */
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 <Int dim>
class EquivalentStrainMazars : public EmptyIteratorContainer {
public:
EquivalentStrainMazars(Material & /*mat*/) {}
template <class D, class... Other>
Real operator()(const Eigen::MatrixBase<D> & epsilon, Other &&... /*other*/) {
auto && [epsilon_hat, _] = tensorPlusTrace<dim>(epsilon);
return std::sqrt(epsilon_hat);
}
};
template <Int dim>
class EquivalentStrainMazarsDruckerPrager : public EquivalentStrainMazars<dim> {
public:
EquivalentStrainMazarsDruckerPrager(Material & mat)
: EquivalentStrainMazars<dim>(mat) {
mat.registerParam("k", k, _pat_parsable, "k");
}
template <class D, class... Other>
- Real operator()(const Eigen::MatrixBase<D> & epsilon, Real) {
+ Real operator()(const Eigen::MatrixBase<D> & epsilon, Other &&... /*other*/) {
Real epsilon_hat = EquivalentStrainMazars<dim>::operator()(epsilon);
epsilon_hat += k * epsilon.trace();
return epsilon_hat;
}
protected:
- Real k;
+ Real k{0.};
};
/* -------------------------------------------------------------------------- */
/* DamageThreshold functions */
/* -------------------------------------------------------------------------- */
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;
+ Real A{0.};
+ Real K0{0.};
};
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 c9bfddd88..bf2e91cd6 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_damage.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_damage.hh
@@ -1,112 +1,108 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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;
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
template <class Args>
inline void computeTangentModuliOnQuad(Args && arguments);
auto getDissipatedEnergy() const -> Real;
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
decltype(auto) getArguments(ElementType el_type,
GhostType ghost_type = _not_ghost) {
return zip_append(Parent<dim>::getArguments(el_type, ghost_type),
"damage"_n = this->damage(el_type, ghost_type),
"previous_damage"_n =
this->damage.previous(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 = this->damage(el_type, ghost_type),
"previous_damage"_n = this->damage.previous(el_type, ghost_type));
}
Real getEnergy(const std::string & type) override;
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;
+ InternalField<Real> & damage;
/// dissipated energy
- InternalField<Real> 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;
+ 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 35da02cb8..5030ba870 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,69 +1,70 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
+#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH_
#define AKANTU_MATERIAL_DAMAGE_NON_LOCAL_HH_
namespace akantu {
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);
+ for (auto type : this->getElementFilter().elementTypes(dim, ghost_type)) {
+ auto & elem_filter = this->getElementFilter(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 21648b2de..1497e38bb 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,153 +1,114 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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);
- this->damage.initializeHistory();
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <Int dim, template <Int> class Parent>
-void MaterialDamage<dim, Parent>::initMaterial() {
- AKANTU_DEBUG_IN();
- Parent<dim>::initMaterial();
- AKANTU_DEBUG_OUT();
+ : Parent<dim>(model, id), damage(this->registerInternal("damage", 1)),
+ dissipated_energy(this->registerInternal("damage dissipated energy", 1)),
+ int_sigma(this->registerInternal("integral of sigma", 1)) {
+ damage.initializeHistory();
}
/* -------------------------------------------------------------------------- */
/**
* 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 <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(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;
+ for (auto && [args, epot, edis, ints] :
+ zip(getArguments(el_type), this->potential_energy(el_type),
+ this->dissipated_energy(el_type), this->int_sigma(el_type))) {
- Real dint = .5 * sigma_h.doubleDot(delta_gradu);
+ Matrix<Real, dim, dim> delta_gradu =
+ args["grad_u"_n] - args["previous_grad_u"_n];
+ Matrix<Real, dim, dim> sigma_h = args["sigma"_n] + args["previous_sigma"_n];
+ auto dint = sigma_h.doubleDot(delta_gradu) / 2;
- *ints += dint;
- *ed = *ints - *epot;
-
- ++epsilon_p;
- ++sigma_p;
- ++epot;
- ++ints;
- ++ed;
-
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ ints += dint;
+ edis = ints - epot;
+ }
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
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();
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 <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 <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(dim, _not_ghost)) {
- de +=
- this->fem.integrate(dissipated_energy(type, _not_ghost), type,
- _not_ghost, this->element_filter(type, _not_ghost));
+ for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+ de += this->getFEEngine().integrate(
+ this->dissipated_energy(type, _not_ghost), type, _not_ghost,
+ this->getElementFilter(type, _not_ghost));
}
-
- AKANTU_DEBUG_OUT();
return de;
}
/* -------------------------------------------------------------------------- */
template <Int dim, template <Int> class Parent>
Real MaterialDamage<dim, Parent>::getEnergy(const std::string & type) {
if (type == "dissipated") {
return getDissipatedEnergy();
}
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 468d51b1b..2d72968f2 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.cc
@@ -1,90 +1,69 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialMarigo<dim>::MaterialMarigo(SolidMechanicsModel & model, const ID & id)
- : MaterialDamage<dim>(model, id), Y("Y", *this), Yd("Yd", *this),
- damage_in_y(false), yc_limit(false) {
- AKANTU_DEBUG_IN();
+ : MaterialDamage<dim>(model, id), Y(this->registerInternal("Y", 1)),
+ Yd(this->template registerInternal<Real, DefaultRandomInternalField>("Yd",
+ 1)) {
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);
- this->Y.initialize(1);
-
- AKANTU_DEBUG_OUT();
-}
-
-/* -------------------------------------------------------------------------- */
-template <Int dim> void MaterialMarigo<dim>::initMaterial() {
- AKANTU_DEBUG_IN();
- MaterialDamage<dim>::initMaterial();
-
- updateInternalParameters();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim> void MaterialMarigo<dim>::updateInternalParameters() {
MaterialDamage<dim>::updateInternalParameters();
- Yc = .5 * epsilon_c * this->E * epsilon_c;
+ Yc = epsilon_c * this->E * epsilon_c / 2.;
yc_limit = (std::abs(epsilon_c) > std::numeric_limits<Real>::epsilon());
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialMarigo<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
- auto && arguments = getArguments(el_type, ghost_type);
-
- for (auto && data : arguments) {
+ for (auto && data : getArguments(el_type, ghost_type)) {
computeStressOnQuad(data);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template class MaterialMarigo<1>;
template class MaterialMarigo<2>;
template class MaterialMarigo<3>;
-static bool material_is_alocated_marigo =
+const 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 225685986..23df1a2d6 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_marigo.hh
@@ -1,120 +1,118 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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.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 <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
template <typename Args> inline void computeStressOnQuad(Args && arguments);
template <typename Args>
inline void computeDamageAndStressOnQuad(Args && arguments);
/* ------------------------------------------------------------------------ */
/* DataAccessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- inline Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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 = this->Yd(el_type, ghost_type),
"Y"_n = this->Y(el_type, ghost_type));
}
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Y, Y, Real);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
- InternalField<Real> Y;
+ InternalField<Real> & Y;
/// resistance to damage
- RandomInternalField<Real> Yd;
+ RandomInternalField<Real> & Yd;
/// damage threshold
Real Sd{5000};
/// critical epsilon when the material is considered as broken
Real epsilon_c{0.};
Real Yc{0.};
bool damage_in_y{false};
bool yc_limit{false};
};
} // 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 a482f8be9..9e16bceb8 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,132 +1,122 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_CC__
// #define __AKANTU_MATERIAL_MARIGO_INLINE_IMPL_CC__
namespace akantu {
/* -------------------------------------------------------------------------- */
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);
+ MaterialElastic<dim>::computeStressOnQuad(
+ std::forward<decltype(arguments)>(arguments));
Y = sigma.doubleDot(Material::gradUToEpsilon<dim>(grad_u)) / 2.;
if (this->damage_in_y) {
Y *= (1 - dam);
}
if (this->yc_limit) {
Y = std::min(Y, this->Yc);
}
if (not this->is_non_local) {
- computeDamageAndStressOnQuad(arguments);
+ computeDamageAndStressOnQuad(std::forward<decltype(arguments)>(arguments));
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <typename Args>
inline void
-MaterialMarigo<dim>::computeDamageAndStressOnQuad(Args && arguments) {
+MaterialMarigo<dim>::computeDamageAndStressOnQuad(Args && arguments) { // NOLINT(cppcoreguidelines-missing-std-forward)
auto && sigma = arguments["sigma"_n];
auto && dam = arguments["damage"_n];
auto && prev_dam = arguments["previous_damage"_n];
auto && Y = arguments["Y"_n];
auto && Yd = arguments["Yd"_n];
Real Fd = Y - Yd - Sd * prev_dam;
if (Fd > 0) {
dam = (Y - Yd) / Sd;
}
dam = std::max(dam, prev_dam);
dam = std::min(dam, 1.);
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
inline auto MaterialMarigo<dim>::getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const
-> Int {
- AKANTU_DEBUG_IN();
-
Int size = 0;
- if (tag == SynchronizationTag::_smm_init_mat) {
+ if (tag == SynchronizationTag::_clh_init_cl) {
size += sizeof(Real) * this->getModel().getNbIntegrationPoints(elements);
}
size += MaterialDamage<dim>::getNbData(elements, tag);
- AKANTU_DEBUG_OUT();
return size;
}
/* -------------------------------------------------------------------------- */
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);
+ if (tag == SynchronizationTag::_clh_init_cl) {
+ this->packInternalFieldHelper(Yd, buffer, elements);
}
MaterialDamage<dim>::packData(buffer, elements, tag);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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);
+ if (tag == SynchronizationTag::_clh_init_cl) {
+ this->unpackInternalFieldHelper(Yd, buffer, elements);
}
MaterialDamage<dim>::unpackData(buffer, elements, tag);
-
- AKANTU_DEBUG_OUT();
}
} // namespace akantu
-//#endif /* __AKANTU_MATERIAL_MARIGO_INLINE_IMPL_CC__ */
+// #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 d0306136c..92882b079 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,87 +1,86 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialMarigoNonLocal<dim>::MaterialMarigoNonLocal(SolidMechanicsModel & model,
const ID & id)
- : parent(model, id), Ynl("Y non local", *this) {
- AKANTU_DEBUG_IN();
+ : parent(model, id),
+ Ynl(this->template registerInternal<Real>("Y non local", 1)) {
this->is_non_local = true;
- this->Ynl.initialize(1);
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialMarigoNonLocal<dim>::registerNonLocalVariables() {
- this->model.getNonLocalManager().registerNonLocalVariable(this->Y.getName(),
- Ynl.getName(), 1);
- this->model.getNonLocalManager()
+ this->getModel().getNonLocalManager().registerNonLocalVariable(
+ this->Y.getName(), Ynl.getName(), 1);
+ this->getModel()
+ .getNonLocalManager()
.getNeighborhood(this->name)
.registerNonLocalVariable(Ynl.getName());
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialMarigoNonLocal<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto && arguments = this->getArguments(el_type, ghost_type);
for (auto && data : arguments) {
MaterialMarigo<dim>::computeStressOnQuad(data);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialMarigoNonLocal<dim>::computeNonLocalStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
auto && arguments = getArgumentsNonLocal(el_type, ghost_type);
for (auto && data : arguments) {
this->computeDamageAndStressOnQuad(data);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template class MaterialMarigoNonLocal<1>;
template class MaterialMarigoNonLocal<2>;
template class MaterialMarigoNonLocal<3>;
-static bool material_is_alocated_marigo_non_local =
+const bool material_is_alocated_marigo_non_local [[maybe_unused]] =
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 befdc78c2..5608ed8b3 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,83 +1,83 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int spatial_dimension>
class MaterialMarigoNonLocal
: public MaterialDamageNonLocal<spatial_dimension,
MaterialMarigo<spatial_dimension>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
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;
public:
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
decltype(auto) getArgumentsNonLocal(ElementType el_type,
GhostType ghost_type) {
return zip_replace(parent::getArguments(el_type, ghost_type),
"Y"_n = this->Ynl(el_type, ghost_type));
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
- InternalField<Real> Ynl;
+ 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 85f4190c6..f1b4bd506 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.cc
@@ -1,35 +1,35 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
namespace akantu {
template class MaterialMazars<1>;
template class MaterialMazars<2>;
template class MaterialMazars<3>;
template <Int dim> using MaterialMazars_ = MaterialMazars<dim>;
-static bool material_is_alocated_mazars =
+const bool material_is_alocated_mazars [[maybe_unused]] =
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 7246a964c..114cce11e 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_mazars.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_mazars.hh
@@ -1,116 +1,115 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_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 <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
template <typename Args> inline void computeStressOnQuad(Args && args);
template <typename Args>
inline void computeDamageAndStressOnQuad(Args && args);
template <typename Args, typename Derived>
inline void
computeDamageOnQuad(Args && args,
const Eigen::MatrixBase<Derived> & epsilon_princ);
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)),
+ "K0"_n = 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;
+ DefaultRandomInternalField<Real> & K0;
/// parameter damage traction 1
- Real At;
+ Real At{0.};
/// parameter damage traction 2
- Real Bt;
+ Real Bt{0.};
/// parameter damage compression 1
- Real Ac;
+ Real Ac{0.};
/// parameter damage compression 2
- Real Bc;
+ Real Bc{0.};
/// parameter for shear
- Real beta;
+ Real beta{0.};
/// specify the variable to average false = ehat, true = damage (only valid
/// for non local version)
- bool damage_in_compute_stress;
+ bool damage_in_compute_stress{true};
Real Ehat{0};
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
#include "material_mazars_inline_impl.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 b11d9547c..d0b1cec46 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,171 +1,172 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
+// #include "material_linear_isotropic_hardening.hh"
+#include "material_mazars.hh" // NOLINT
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) {
+ : parent_damage(model, id),
+ K0(this->template registerInternal<Real, DefaultRandomInternalField>("K0",
+ 1)) {
+
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 <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);
+ Parent<dim>::computeStressOnQuad(std::forward<decltype(args)>(args));
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 (Int i = 0; i < 3; ++i) {
Real epsilon_p = std::max(Real(0.), Fdiag(i));
Ehat += epsilon_p * epsilon_p;
}
Ehat = std::sqrt(Ehat);
if (damage_in_compute_stress) {
computeDamageOnQuad(args, Fdiag);
}
if (not this->is_non_local) {
computeDamageAndStressOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
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);
+ computeDamageOnQuad(std::forward<Args>(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 <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 && K0 = args["K0"_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.));
}
} // 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 36238fa37..564fea782 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,84 +1,84 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim, template <Int> class Parent = MaterialElastic>
class MaterialMazarsNonLocal
: public MaterialDamageNonLocal<dim, MaterialMazars<dim, Parent>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
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> & Ehat;
- InternalField<Real> non_local_variable;
+ 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
index b2f706eea..fdd3916ab 100644
--- 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
@@ -1,108 +1,101 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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) {
+ : parent(model, id), Ehat(this->registerInternal("Ehat", 1)),
+ non_local_variable(this->registerInternal("non_local_variable", 1)) {
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(
+ this->getModel().getNonLocalManager().registerNonLocalVariable(
local, non_local_variable.getName(), 1);
- this->model.getNonLocalManager()
+ this->getModel()
+ .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 bb1f72cf7..ba110bb58 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield.cc
@@ -1,100 +1,99 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialPhaseField<dim>::MaterialPhaseField(SolidMechanicsModel & model,
const ID & id)
- : Parent(model, id), effective_damage("effective_damage", *this) {
+ : Parent(model, id),
+ effective_damage(this->registerInternal("effective_damage", 1)) {
this->registerParam("eta", eta, Real(0.), _pat_parsable, "eta");
this->registerParam("is_hybrid", is_hybrid, false,
_pat_parsable | _pat_readable, "Use hybrid formulation");
- this->damage.initialize(0);
- this->effective_damage.initialize(1);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialPhaseField<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
if (this->is_hybrid) {
computeEffectiveDamage(el_type, ghost_type);
for (auto && args : getArguments(el_type, ghost_type)) {
auto && dam = args["effective_damage"_n];
computeStressOnQuad(tuple::replace(args, "damage"_n = dam));
}
} else {
for (auto && args : getArguments(el_type, ghost_type)) {
computeStressOnQuad(args);
}
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialPhaseField<dim>::computeTangentModuli(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type) {
computeEffectiveDamage(el_type, ghost_type);
if (this->is_hybrid) {
computeEffectiveDamage(el_type, ghost_type);
for (auto && args :
getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
auto && dam = args["effective_damage"_n];
computeTangentModuliOnQuad(tuple::replace(args, "damage"_n = dam));
}
} else {
for (auto && args :
getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
computeTangentModuliOnQuad(args);
}
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialPhaseField<dim>::computeEffectiveDamage(ElementType el_type,
GhostType ghost_type) {
for (auto && args : getArguments(el_type, ghost_type)) {
computeEffectiveDamageOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
template class MaterialPhaseField<1>;
template class MaterialPhaseField<2>;
template class MaterialPhaseField<3>;
-static bool material_is_allocated_phasefield =
+const bool material_is_allocated_phasefield [[maybe_unused]] =
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 4705ba0f3..6f9dca0b2 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield.hh
@@ -1,105 +1,103 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#ifndef AKANTU_MATERIAL_PHASEFIELD_HH_
+#define AKANTU_MATERIAL_PHASEFIELD_HH_
namespace akantu {
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);
template <class Args> inline void computeEffectiveDamageOnQuad(Args && args);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
- /// Residual stiffness parameter
- Real eta;
+ Real eta{0.};
/// Phasefield isotropic
bool is_hybrid;
- /// effective damage to conserve stiffness in compression
- InternalField<Real> effective_damage;
+ // 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__ */
+#endif /* AKANTU_MATERIAL_PHASEFIELD_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc b/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc
index d6cfc3337..cbacdfdc4 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic.cc
@@ -1,118 +1,117 @@
/**
* @file material_phasefield_anisotropic.cc
*
* @author Shad Durussel <shad.durussel@epfl.ch>
*
* @date creation: Mon Mar 27 2023
* @date last modification: Mon Mar 27 2023
*
* @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_anisotropic.hh"
#include "aka_common.hh"
#include "solid_mechanics_model.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
template <Int dim>
MaterialPhaseFieldAnisotropic<dim>::MaterialPhaseFieldAnisotropic(
SolidMechanicsModel & model, const ID & id)
: Parent(model, id) {
this->registerParam("eta", eta, Real(0.), _pat_parsable, "eta");
this->registerParam("is_isotropic", is_isotropic, false,
_pat_parsable | _pat_readable,
"Use isotropic formulation");
- this->damage.initialize(0);
}
template <Int dim>
void MaterialPhaseFieldAnisotropic<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
auto && arguments = Parent::getArguments(el_type, ghost_type);
if (not this->finite_deformation) {
for (auto && args : arguments) {
this->computeStressOnQuad(args);
}
} else {
for (auto && args : arguments) {
auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
this->computeStressOnQuad(tuple::replace(args, "grad_u"_n = E));
}
}
}
/* -------------------------------------------------------------------------- */
template <Int dim> void MaterialPhaseFieldAnisotropic<dim>::initMaterial() {
MaterialDamage<dim>::initMaterial();
}
/* -------------------------------------------------------------------------- */
template <> void MaterialPhaseFieldAnisotropic<2>::initMaterial() {
MaterialDamage<2>::initMaterial();
this->dev_dim = 2;
if (!this->plane_stress) {
this->dev_dim = 3;
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialPhaseFieldAnisotropic<dim>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
auto && arguments =
Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type);
if (not this->finite_deformation) {
for (auto && args : arguments) {
this->computeTangentModuliOnQuad(args);
}
} else {
for (auto && args : arguments) {
auto && E = this->template gradUToE<dim>(args["grad_u"_n]);
this->computeTangentModuliOnQuad(tuple::replace(args, "grad_u"_n = E));
}
}
// for (auto && args :
// Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
// computeTangentModuliOnQuad(args);
// }
}
/* -------------------------------------------------------------------------- */
template class MaterialPhaseFieldAnisotropic<1>;
template class MaterialPhaseFieldAnisotropic<2>;
template class MaterialPhaseFieldAnisotropic<3>;
static bool material_is_allocated_phasefield =
instantiateMaterial<MaterialPhaseFieldAnisotropic>(
"phasefield_anisotropic");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh b/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh
index 491bd8875..a33769018 100644
--- a/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh
+++ b/src/model/solid_mechanics/materials/material_damage/material_phasefield_anisotropic_inline_impl.hh
@@ -1,134 +1,134 @@
/**
* @file material_phasefield_anisotropic_inline_impl.cc
*
* @author Shad Durussel <shad.durussel@epfl.ch>
*
* @date creation: Mon Mar 27 2023
* @date last modification: Mon Mar 27 2023
*
* @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_anisotropic.hh"
#include <algorithm>
#ifndef AKANTU_MATERIAL_PHASEFIELD_ANISOTROPIC_INLINE_IMPL_HH_
#define AKANTU_MATERIAL_PHASEFIELD_ANISOTROPIC_INLINE_IMPL_HH_
/* -------------------------------------------------------------------------- */
namespace akantu {
template <Int dim>
template <class Args>
inline void
MaterialPhaseFieldAnisotropic<dim>::computeStressOnQuad(Args && args) {
// MaterialElastic<dim>::computeStressOnQuad(args);
auto && dam = args["damage"_n];
auto sigma = args["sigma"_n];
auto strain = Material::gradUToEpsilon<dim>(args["grad_u"_n]);
Real trace = strain.trace();
Real trace_plus = std::max(Real(0.), trace);
Real trace_minus = std::min(Real(0.), trace);
Real sigma_th_plus = std::max(Real(0.), args["sigma_th"_n]);
Real sigma_th_minus = std::min(Real(0.), args["sigma_th"_n]);
Matrix<Real> strain_dev(dev_dim, dev_dim);
Matrix<Real> strain_tmp = Matrix<Real>::Zero(dev_dim, dev_dim);
strain_tmp.topLeftCorner(dim, dim) = strain;
strain_dev = strain_tmp - trace / Real(dev_dim) * Matrix<Real>::Identity(dev_dim, dev_dim);
Real kappa = this->lambda + 2. / Real(dev_dim) * this->mu;
Real g_d = (1 - dam) * (1 - dam) + eta;
auto sigma_plus = (kappa * trace_plus + sigma_th_plus) *
- Matrix<Real>::Identity(dim, dim) +
+ Matrix<Real>::Identity(dev_dim, dev_dim) +
2. * this->mu * strain_dev;
auto sigma_minus = (kappa * trace_minus + sigma_th_minus) *
- Matrix<Real>::Identity(dim, dim);
+ Matrix<Real>::Identity(dev_dim , dev_dim);
- sigma = g_d * sigma_plus + sigma_minus;
+ sigma = g_d * sigma_plus.topLeftCorner(dim, dim) + sigma_minus.topLeftCorner(dim, dim);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class Args>
void MaterialPhaseFieldAnisotropic<dim>::computeTangentModuliOnQuad(
Args && args) {
auto && dam = args["damage"_n];
auto strain = Material::gradUToEpsilon<dim>(args["grad_u"_n]);
Real trace = strain.trace();
Real g_d = (1 - dam) * (1 - dam) + eta;
Real g_d_hyd = trace > 0. ? g_d : 1.;
auto && tangent = args["tangent_moduli"_n];
tangent.zero();
constexpr auto n = Material::getTangentStiffnessVoigtSize(dim);
// Real Ep = E/((1+nu)*(1-2*nu));
if constexpr (dim == 1) {
tangent(0, 0) = g_d_hyd * this->E;
return;
}
Real kappa = this->lambda + 2. / Real(dim) * this->mu;
auto Miiii = g_d_hyd * kappa + g_d * 2. * this->mu * (1. - 1. / Real(dev_dim));
[[maybe_unused]] auto Miijj = g_d_hyd * kappa - g_d * 2. * this->mu / Real(dev_dim);
[[maybe_unused]] auto Mijij = g_d * this->mu;
tangent(0, 0) = Miiii;
// test of dimension should by optimized out by the compiler due to the
// template
if constexpr (dim >= 2) {
tangent(1, 1) = Miiii;
tangent(0, 1) = Miijj;
tangent(1, 0) = Miijj;
tangent(n - 1, n - 1) = Mijij;
}
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;
}
}
} // namespace akantu
#endif
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 114997f2e..b90aca612 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,38 +1,38 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_linear_isotropic_hardening.hh"
#include "material_mazars.hh"
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_MATERIAL_VONMISES_MAZARS_HH__
-#define __AKANTU_MATERIAL_VONMISES_MAZARS_HH__
+#ifndef AKANTU_MATERIAL_VONMISES_MAZARS_HH_
+#define AKANTU_MATERIAL_VONMISES_MAZARS_HH_
namespace akantu {
template <Int dim>
using MaterialVonMisesMazars =
MaterialMazars<dim, MaterialLinearIsotropicHardening>;
} // namespace akantu
#endif /* __AKANTU_MATERIAL_VONMISES_MAZARS_HH__ */
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 896cbe50a..ff29ef169 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,34 +1,34 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
namespace akantu {
template class MaterialMazarsNonLocal<1, MaterialLinearIsotropicHardening>;
template class MaterialMazarsNonLocal<2, MaterialLinearIsotropicHardening>;
template class MaterialMazarsNonLocal<3, MaterialLinearIsotropicHardening>;
-static bool material_is_allocated_plastic_mazars_non_local =
+const bool material_is_allocated_plastic_mazars_non_local [[maybe_unused]] =
instantiateMaterial<MaterialVonMisesMazarsNonLocal>(
"plastic_mazars_non_local");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_elastic.cc b/src/model/solid_mechanics/materials/material_elastic.cc
index 90fb88a4d..55e6fae75 100644
--- a/src/model/solid_mechanics/materials/material_elastic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic.cc
@@ -1,241 +1,219 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 <Int dim>
-MaterialElastic<dim>::MaterialElastic(SolidMechanicsModel & model,
- 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 <Int dim> void MaterialElastic<dim>::initialize() {
+ const ID & id, const ID & fe_engine_id)
+ : Parent(model, id, fe_engine_id) {
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 <Int dim> void MaterialElastic<dim>::initMaterial() {
AKANTU_DEBUG_IN();
Parent::initMaterial();
if (dim == 1) {
this->nu = 0.;
}
this->updateInternalParameters();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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 <Int dim>
void MaterialElastic<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
Parent::computeStress(el_type, ghost_type);
auto && arguments = Parent::getArguments(el_type, ghost_type);
if (not this->finite_deformation) {
for (auto && args : arguments) {
this->computeStressOnQuad(args);
}
} else {
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 <Int dim>
void MaterialElastic<dim>::computeTangentModuli(ElementType el_type,
Array<Real> & tangent_matrix,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
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 <Int dim>
-Real MaterialElastic<dim>::getPushWaveSpeed(const Element &) const {
+Real MaterialElastic<dim>::getPushWaveSpeed(const Element & /*element*/) const {
return sqrt((lambda + 2 * mu) / this->rho);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
-Real MaterialElastic<dim>::getShearWaveSpeed(const Element &) const {
+Real MaterialElastic<dim>::getShearWaveSpeed(
+ const Element & /*element*/) const {
return sqrt(mu / this->rho);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialElastic<dim>::computePotentialEnergy(ElementType el_type) {
AKANTU_DEBUG_IN();
// needs to be implemented
// MaterialThermal<dim>::computePotentialEnergy(el_type);
-
- auto epot = this->potential_energy(el_type, _not_ghost).begin();
-
auto && arguments = Parent::getArguments(el_type, _not_ghost);
if (not this->finite_deformation) {
for (auto && [args, epot] :
zip(arguments, this->potential_energy(el_type, _not_ghost))) {
this->computePotentialEnergyOnQuad(args, epot);
}
} else {
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 <Int dim>
void MaterialElastic<dim>::computePotentialEnergyByElement(
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_view = make_view<dim, dim>(this->piola_kirchhoff_2(type));
+ stress_view = make_view<dim, dim>((*this->piola_kirchhoff_2)(type));
}
- auto nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
+ auto nb_quadrature_points = this->getFEEngine().getNbIntegrationPoints(type);
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;
auto epot_quad = epot_on_quad_points.begin();
- Matrix<Real> grad_u(dim, dim);
-
if (this->finite_deformation) {
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 (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>;
-static bool material_is_allocated_elastic =
+const bool material_is_allocated_elastic [[maybe_unused]] =
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 c04602eb1..5a9725e4b 100644
--- a/src/model/solid_mechanics/materials/material_elastic.hh
+++ b/src/model/solid_mechanics/materials/material_elastic.hh
@@ -1,146 +1,141 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
class MaterialElastic : public PlaneStressToolbox<dim, MaterialThermal<dim>> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
private:
using Parent = PlaneStressToolbox<dim, MaterialThermal<dim>>;
public:
- MaterialElastic(SolidMechanicsModel & model, const ID & id = "");
- MaterialElastic(SolidMechanicsModel & model, Int spatial_dimension,
- const Mesh & mesh, FEEngine & fe_engine, const ID & id = "");
-
- ~MaterialElastic() override = default;
-
-protected:
- void initialize();
+ MaterialElastic(SolidMechanicsModel & model, const ID & id = "",
+ const ID & fe_engine_id = "");
/* ------------------------------------------------------------------------ */
/* 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;
[[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(const Element & element,
Vector<Real> & epot_on_quad_points) override;
/// compute the p-wave speed in the material
- auto getPushWaveSpeed(const Element & element) const -> Real override;
+ [[nodiscard]] auto getPushWaveSpeed(const Element & element) const
+ -> Real override;
/// compute the s-wave speed in the material
- auto getShearWaveSpeed(const Element & element) const -> Real override;
+ [[nodiscard]] auto getShearWaveSpeed(const Element & element) const
+ -> Real override;
protected:
/// constitutive law for a given quadrature point
template <typename Args> inline void computeStressOnQuad(Args && args) const;
/// compute the tangent stiffness matrix for an element
template <typename Args>
inline void computeTangentModuliOnQuad(Args && args) const;
/// recompute the lame coefficient if E or nu changes
void updateInternalParameters() override;
template <class Args>
static inline void computePotentialEnergyOnQuad(Args && args, Real & epot);
auto hasStiffnessMatrixChanged() -> bool override {
return (not was_stiffness_assembled);
}
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;
+ Real lambda{0.};
/// Second Lamé coefficient (shear modulus)
- Real mu;
+ Real mu{0.};
/// Bulk modulus
- Real kpa;
+ Real kpa{0.};
/// defines if the stiffness was computed
- bool was_stiffness_assembled;
+ bool was_stiffness_assembled{false};
};
} // namespace akantu
#include "material_elastic_inline_impl.hh"
#endif /* AKANTU_MATERIAL_ELASTIC_HH_ */
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 158e5c66d..772f9b251 100644
--- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.cc
@@ -1,248 +1,240 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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) {
+ symmetric(symmetric) {
AKANTU_DEBUG_IN();
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 (auto i : arange(voigt_h::size)) {
decltype(i) start = 0;
if (this->symmetric) {
start = i;
}
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 <Int dim> void MaterialElasticLinearAnisotropic<dim>::initMaterial() {
- AKANTU_DEBUG_IN();
- Material::initMaterial();
- AKANTU_DEBUG_OUT();
-}
-
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::updateInternalParameters() {
Material::updateInternalParameters();
if (this->symmetric) {
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 <Int Dim> void MaterialElasticLinearAnisotropic<Dim>::rotateCprime() {
// start by filling the empty parts fo Cprime
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 (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
+ // construction of rotator tensor normalize rotation matrix
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
Real test_axis = 0.;
- if (Dim == 2) {
+ if constexpr (Dim == 2) {
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);
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) {
+ } else if constexpr (Dim == 3) {
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();
}
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 << ".");
}
// create the rotator and the reverse rotator
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, Dim * Dim, Dim * Dim> Cfull(Dim * Dim, Dim * Dim);
+ Matrix<Real, Dim * Dim, Dim * Dim> Cfull;
Cfull = rotator * Cprime * revrotor;
for (auto i : arange(voigt_h::size)) {
for (auto j : arange(voigt_h::size)) {
this->C(i, j) = Cfull(i, j);
}
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computeStress(
ElementType el_type, GhostType ghost_type) {
auto && arguments = getArguments(el_type, ghost_type);
for (auto && data : arguments) {
this->computeStressOnQuad(data);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
auto && arguments =
Material::getArgumentsTangent<dim>(tangent_matrix, el_type, ghost_type);
for (auto && args : arguments) {
this->computeTangentModuliOnQuad(args);
}
this->was_stiffness_assembled = true;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computePotentialEnergy(
ElementType el_type) {
AKANTU_DEBUG_ASSERT(!this->finite_deformation,
"finite deformation not possible in material anisotropic "
"(TO BE IMPLEMENTED)");
auto && arguments = Material::getArguments<dim>(el_type, _not_ghost);
- for (auto && args :
- zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+ for (auto && args : zip(arguments, potential_energy(el_type, _not_ghost))) {
this->computePotentialEnergyOnQuad(std::get<0>(args), std::get<1>(args));
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialElasticLinearAnisotropic<dim>::computePotentialEnergyByElement(
ElementType type, Int index, Vector<Real> & epot_on_quad_points) {
+ const auto & fem = this->getFEEngine();
auto gradu_view = make_view<dim, dim>(this->gradu(type));
auto stress_view = make_view<dim, dim>(this->stress(type));
- auto nb_quadrature_points = this->fem.getNbIntegrationPoints(type);
+ auto nb_quadrature_points = 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 <Int dim>
Real MaterialElasticLinearAnisotropic<dim>::getCelerity(
const Element & /*element*/) const {
return std::sqrt(this->eigC(0) / rho);
}
/* -------------------------------------------------------------------------- */
template class MaterialElasticLinearAnisotropic<1>;
template class MaterialElasticLinearAnisotropic<2>;
template class MaterialElasticLinearAnisotropic<3>;
-static bool material_is_alocated_elastic =
+const bool material_is_alocated_elastic [[maybe_unused]] =
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 e19541ca9..12f1c1efb 100644
--- a/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
+++ b/src/model/solid_mechanics/materials/material_elastic_linear_anisotropic.hh
@@ -1,133 +1,131 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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
template <typename Args> inline void computeStressOnQuad(Args && args) const;
/// tangent matrix for a given quadrature point
template <typename Args>
inline void computeTangentModuliOnQuad(Args && args) const;
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>;
/// direction matrix and vectors
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;
+ bool was_stiffness_assembled{false};
};
} // 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 b25c31b78..063b17872 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,66 +1,65 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
template <typename Args>
inline void
-MaterialElasticLinearAnisotropic<dim>::computeStressOnQuad(Args && args) const {
+MaterialElasticLinearAnisotropic<dim>::computeStressOnQuad(Args && args) const { // NOLINT(cppcoreguidelines-
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 <Int dim>
template <class Args>
inline void MaterialElasticLinearAnisotropic<dim>::computeTangentModuliOnQuad(
Args && args) const {
args["tangent_moduli"_n] = this->C;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class Args>
inline void MaterialElasticLinearAnisotropic<dim>::computePotentialEnergyOnQuad(
Args && args, Real & epot) {
-
AKANTU_DEBUG_ASSERT(this->symmetric,
"The elastic constants matrix is not symmetric,"
"energy is not path independent.");
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 a0e2fbbfd..478f97381 100644
--- a/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
+++ b/src/model/solid_mechanics/materials/material_elastic_orthotropic.cc
@@ -1,138 +1,138 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 <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 <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
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 class MaterialElasticOrthotropic<1>;
template class MaterialElasticOrthotropic<2>;
template class MaterialElasticOrthotropic<3>;
-static bool material_is_allocated_elastic_orthotropic =
+const bool material_is_allocated_elastic_orthotropic [[maybe_unused]] =
instantiateMaterial<MaterialElasticOrthotropic>("elastic_orthotropic");
} // namespace akantu
diff --git a/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh b/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
deleted file mode 100644
index 84929f4ad..000000000
--- a/src/model/solid_mechanics/materials/material_embedded/material_embedded_includes.hh
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * 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_CMAKE_LIST_MATERIALS
-#include "material_reinforcement.hh"
-#endif
-
-#define AKANTU_MATERIAL_REINFORCEMENT_LAW_TMPL_LIST \
- ((elastic, (MaterialElastic<1>)))( \
- (plastic, (MaterialLinearIsotropicHardening<1>)))
-
-#define AKANTU_EMBEDDED_MATERIAL_LIST \
- ((2, (reinforcement, MaterialReinforcement)))
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 5bf9c7db3..937df2356 100644
--- a/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
+++ b/src/model/solid_mechanics/materials/material_embedded/material_reinforcement.hh
@@ -1,193 +1,193 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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, 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.
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<Idx> & filter);
/// Filter elements crossed by interface of a type
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);
/// Get background filter
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<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;
+ std::shared_ptr<InternalField<Real>> gradu_embedded;
/// C matrix on quad
- InternalField<Real> directing_cosines;
+ std::shared_ptr<InternalField<Real>> directing_cosines;
/// Prestress on quad
- InternalField<Real> pre_stress;
+ std::shared_ptr<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<Idx> foreground_filter;
/// Background element filter (contains bg ids)
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 c2cf2d12c..f69e99e6d 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,679 +1,649 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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, Int dim>
-void MaterialReinforcement<Mat, dim>::initialize() {
- AKANTU_DEBUG_IN();
-
+ : Mat(model, id, "EmbeddedInterfaceFEEngine"), emodel(model), area(1.0) {
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, Int dim>
-MaterialReinforcement<Mat, dim>::~MaterialReinforcement() {
- AKANTU_DEBUG_IN();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <class Mat, Int dim>
void MaterialReinforcement<Mat, dim>::initMaterial() {
Mat::initMaterial();
- gradu_embedded.initialize(dim * dim);
- pre_stress.initialize(1);
+ gradu_embedded = this->registerInternal("gradu_embedded", dim * dim,
+ "EmbeddedInterfaceFEEngine");
+ pre_stress =
+ this->registerInternal("pre_stress", 1, "EmbeddedInterfaceFEEngine");
/// 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, 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<Idx>>(
"bg_" + shaped_id, this->name),
type, gt);
auto & foreground = foreground_filter(
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, Int dim>
void MaterialReinforcement<Mat, dim>::filterInterfaceBackgroundElements(
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);
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(Int spatial_dimension, FEEngine & engine,
ElementType foreground_type,
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, 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, 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, Int dim>
void MaterialReinforcement<Mat, dim>::computeBackgroundShapeDerivatives(
ElementType interface_type, ElementType bg_type, GhostType ghost_type,
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 (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, 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);
+ const auto voigt_size = VoigtHelper<dim>::size;
+ directing_cosines = this->registerInternal("directing_cosines", voigt_size,
+ "EmbeddedInterfaceFEEngine");
for (auto && type : mesh.elementTypes(1, _not_ghost)) {
computeDirectingCosines(type, _not_ghost);
- // computeDirectingCosines(*type_it, _ghost);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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, 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, 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, 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, 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, Int dim>
void MaterialReinforcement<Mat, dim>::assembleInternalForcesInterface(
ElementType interface_type, ElementType background_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
constexpr auto voigt_size = VoigtHelper<dim>::size;
FEEngine & interface_engine = emodel.getFEEngine("EmbeddedInterfaceFEEngine");
const auto & elem_filter = this->element_filter(interface_type, ghost_type);
auto nodes_per_background_e = Mesh::getNbNodesPerElement(background_type);
auto nb_quadrature_points =
interface_engine.getNbIntegrationPoints(interface_type, ghost_type);
auto nb_element = elem_filter.size();
auto back_dof = dim * nodes_per_background_e;
const auto & shapesd = (*shape_derivatives(interface_type, ghost_type))(
background_type, ghost_type);
Array<Real> integrant(nb_quadrature_points * nb_element, back_dof,
"integrant");
Matrix<Real> Bvoigt(voigt_size, back_dof);
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);
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<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, Int dim>
void MaterialReinforcement<Mat, dim>::computeDirectingCosines(
ElementType type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
Mesh & interface_mesh = emodel.getInterfaceMesh();
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));
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, 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, Int dim>
void MaterialReinforcement<Mat, dim>::assembleStiffnessMatrixInterface(
ElementType interface_type, ElementType background_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
constexpr Int voigt_size = VoigtHelper<dim>::size;
FEEngine & interface_engine = emodel.getFEEngine("EmbeddedInterfaceFEEngine");
Array<Idx> & elem_filter = this->element_filter(interface_type, ghost_type);
Array<Real> & grad_u = gradu_embedded(interface_type, ghost_type);
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);
Int back_dof = dim * nodes_per_background_e;
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);
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);
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, 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, 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 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, dim, dim> concrete_du(dim, dim);
Matrix<Real, dim, dim> epsilon(dim, dim);
Vector<Real, voigt_size> evoigt(voigt_size);
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))) {
concrete_du = u * B.transpose();
auto epsilon = 0.5 * (concrete_du + concrete_du.transpose());
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, Int dim>
template <class Derived1, class Derived2>
inline void MaterialReinforcement<Mat, dim>::computeDirectingCosinesOnQuad(
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);
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();
}
/* -------------------------------------------------------------------------- */
} // 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 7a1690b94..634678288 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,234 +1,164 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int spatial_dimension>
MaterialNeohookean<spatial_dimension>::MaterialNeohookean(
SolidMechanicsModel & model, const ID & 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 <Int spatial_dimension>
void MaterialNeohookean<spatial_dimension>::initMaterial() {
PlaneStressToolbox<spatial_dimension>::initMaterial();
if (spatial_dimension == 1) {
nu = 0.;
}
this->updateInternalParameters();
}
/* -------------------------------------------------------------------------- */
template <> void MaterialNeohookean<2>::initMaterial() {
PlaneStressToolbox<2>::initMaterial();
this->updateInternalParameters();
-
- if (this->plane_stress) {
- this->third_axis_deformation.setDefaultValue(1.);
- }
}
/* -------------------------------------------------------------------------- */
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 <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) {
- auto && grad_u = *gradu_it;
- auto && piola = *piola_it;
- auto && sigma = *stress_it;
-
- StoCauchy<2>(gradUToF<2>(grad_u), piola, sigma, *c33_it);
+ for (auto && [grad_u, piola, sigma, c33] :
+ zip(make_view<2, 2>(this->gradu(el_type, ghost_type)),
+ make_view<2, 2>((*this->piola_kirchhoff_2)(el_type, ghost_type)),
+ make_view<2, 2>(this->stress(el_type, ghost_type)),
+ make_view(this->third_axis_deformation(el_type, ghost_type)))) {
+ StoCauchy<2>(gradUToF<2>(grad_u), piola, sigma, c33);
}
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialNeohookean<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
+ PlaneStressToolbox<dim>::computeStress(el_type, ghost_type);
for (auto && args : this->getArguments(el_type, ghost_type)) {
computeStressOnQuad(args);
}
}
-/* -------------------------------------------------------------------------- */
-template <>
-void MaterialNeohookean<2>::computeStress(ElementType el_type,
- GhostType ghost_type) {
- auto && arguments = getArguments(el_type, ghost_type);
- if (this->plane_stress) {
- PlaneStressToolbox<2>::computeStress(el_type, ghost_type);
-
- for (auto && args : zip_replace(
- std::forward<decltype(arguments)>(arguments),
- "C33"_n = this->third_axis_deformation(el_type, ghost_type))) {
- computeStressOnQuad(args);
- }
- } else {
- for (auto && args : arguments) {
- computeStressOnQuad(args);
- }
- }
-}
-
/* -------------------------------------------------------------------------- */
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_ASSERT(this->plane_stress, "The third component of the strain "
"can only be computed for 2D "
"problems in Plane Stress!!");
- for (auto && args : zip_replace(
- getArguments(el_type, ghost_type),
- "C33"_n = this->third_axis_deformation(el_type, ghost_type))) {
+ for (auto && args : getArguments(el_type, ghost_type)) {
computeThirdAxisDeformationOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
-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;
+template <Int dim>
+void MaterialNeohookean<dim>::computePotentialEnergy(ElementType el_type) {
+ Parent::computePotentialEnergy(el_type);
+ auto && arguments = Parent::getArguments(el_type, _not_ghost);
- AKANTU_DEBUG_OUT();
+ for (auto && [args, epot] :
+ zip(arguments, this->potential_energy(el_type, _not_ghost))) {
+ this->computePotentialEnergyOnQuad(args, epot);
+ }
}
/* -------------------------------------------------------------------------- */
-template <Int spatial_dimension>
-void MaterialNeohookean<spatial_dimension>::computeTangentModuli(
- ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
- auto && arguments = getArgumentsTangent(tangent_matrix, el_type, ghost_type);
+template <Int dim>
+void MaterialNeohookean<dim>::computeTangentModuli(ElementType el_type,
+ Array<Real> & tangent_matrix,
+ GhostType ghost_type) {
+ auto && arguments =
+ Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type);
+ Parent::computeStress(el_type, ghost_type);
for (auto && args : arguments) {
computeTangentModuliOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
-template <>
-void MaterialNeohookean<2>::computeTangentModuli(ElementType el_type,
- Array<Real> & tangent_matrix,
- GhostType ghost_type) {
- if (this->plane_stress) {
- PlaneStressToolbox<2>::computeStress(el_type, ghost_type);
-
- 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 {
- for (auto && args :
- getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
- computeTangentModuliOnQuad(args);
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-template <Int spatial_dimension>
-Real MaterialNeohookean<spatial_dimension>::getPushWaveSpeed(
+template <Int dim>
+Real MaterialNeohookean<dim>::getPushWaveSpeed(
const Element & /*element*/) const {
- return sqrt((this->lambda + 2 * this->mu) / this->rho);
+ return std::sqrt((this->lambda + 2 * this->mu) / this->rho);
}
/* -------------------------------------------------------------------------- */
-template <Int spatial_dimension>
-Real MaterialNeohookean<spatial_dimension>::getShearWaveSpeed(
+template <Int dim>
+Real MaterialNeohookean<dim>::getShearWaveSpeed(
const Element & /*element*/) const {
- return sqrt(this->mu / this->rho);
+ return std::sqrt(this->mu / this->rho);
}
/* -------------------------------------------------------------------------- */
template class MaterialNeohookean<1>;
template class MaterialNeohookean<2>;
template class MaterialNeohookean<3>;
-static bool material_is_allocated_neohookean =
+const bool material_is_allocated_neohookean [[maybe_unused]] =
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 33115e858..5d31fe203 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,174 +1,152 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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;
+ [[nodiscard]] Real getPushWaveSpeed(const Element & element) const override;
/// compute the s-wave speed in the material
- Real getShearWaveSpeed(const Element & element) const override;
+ [[nodiscard]] 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
template <class Args> inline void computeStressOnQuad(Args && args);
/// constitutive law for a given quadrature point
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);
+ template <class Args>
+ inline void computePotentialEnergyOnQuad(Args && args, Real & epot);
/// compute the tangent stiffness matrix for an element
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;
+ Real E{0.};
/// Poisson coefficient
- Real nu;
+ Real nu{0.};
/// First Lamé coefficient
- Real lambda;
+ Real lambda{0.};
/// Second Lamé coefficient (shear modulus)
- Real mu;
+ Real mu{0.};
/// Bulk modulus
- Real kpa;
-
- Real C33{1.};
+ Real kpa{0.};
};
} // 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 e8c349aeb..0a598cb08 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,160 +1,156 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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) {}
+ const Matrix<Real> & /*grad_u*/, const Matrix<Real> & /*grad_delta_u*/,
+ Matrix<Real> & /*cddelta_S*/) {}
//! computes the second piola kirchhoff stress, called S
template <Int dim>
template <class Args>
inline void MaterialNeohookean<dim>::computeStressOnQuad(Args && args) {
// Neo hookean book
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<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) {}
+ C33_NR(const ID & name, const Real & lambda, Real mu, const Matrix<Real> & C)
+ : NewtonRaphsonFunctor(name), lambda(lambda), mu(mu), C(C) {}
- inline Real f(const Real & x) const override {
+ [[nodiscard]] 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(const Real & x) const override {
+ [[nodiscard]] 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 Real mu;
const Matrix<Real> & C;
};
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class Args>
inline void
MaterialNeohookean<dim>::computeThirdAxisDeformationOnQuad(Args && args) {
// Neo hookean book
auto F = Material::gradUToF<dim>(args["grad_u"_n]);
auto C = Material::rightCauchy<dim>(F);
Math::NewtonRaphson<Real> nr(1e-5, 100);
auto & C33 = args["C33"_n];
C33 = nr.solve(C33_NR("Neohookean_plan_stress", this->lambda, this->mu, C),
C33);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
inline void
MaterialNeohookean<dim>::computePiolaKirchhoffOnQuad(const Matrix<Real> & E,
Matrix<Real> & S) {
/// \f$ \sigma_{ij} = \lambda * (\nabla u)_{kk} * \delta_{ij} + \mu * (\nabla
/// u_{ij} + \nabla u_{ji}) \f$
S = Matrix<Real, dim, dim>::Identity() * lambda * E.trace() + 2.0 * mu * E;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
inline void MaterialNeohookean<dim>::computeFirstPiolaKirchhoffOnQuad(
const Matrix<Real> & grad_u, const Matrix<Real> & S, Matrix<Real> & P) {
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 <Int dim>
-inline void MaterialNeohookean<dim>::computePotentialEnergyOnQuad(
- const Matrix<Real> & grad_u, Real & epot) {
- auto F = Material::gradUToF<dim>(grad_u);
+template <class Args>
+inline void MaterialNeohookean<dim>::computePotentialEnergyOnQuad(Args && args,
+ Real & epot) {
+ auto F = Material::gradUToF<dim>(args["grad_u"_n]);
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));
+ lambda * pow(log(J), 2.) + mu * (-log(J) + (C.trace() - dim) / 2.) / 2.;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class Args>
inline void MaterialNeohookean<dim>::computeTangentModuliOnQuad(Args && args) {
auto & tangent = args["tangent_moduli"_n];
// Neo hookean book
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 J = F.determinant() * std::sqrt(args["C33"_n]);
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];
+ auto && [i, j] = VoigtHelper<dim>::vec[m];
for (Int n = 0; n < cols; n++) {
- UInt k = VoigtHelper<dim>::vec[n][0];
- UInt l = VoigtHelper<dim>::vec[n][1];
+ auto && [k, l] = VoigtHelper<dim>::vec[n];
// 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 6778a70bd..f057b5cec 100644
--- a/src/model/solid_mechanics/materials/material_non_local.hh
+++ b/src/model/solid_mechanics/materials/material_non_local.hh
@@ -1,106 +1,48 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "constitutive_law_non_local_interface.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_MATERIAL_NON_LOCAL_HH_
#define AKANTU_MATERIAL_NON_LOCAL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
-class MaterialNonLocalInterface {
+class MaterialNonLocalInterface : public ConstitutiveLawNonLocalInterface {
/* ------------------------------------------------------------------------ */
/* 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 <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; }
-};
+using MaterialNonLocal =
+ ConstitutiveLawNonLocal<dim, MaterialNonLocalInterface, LocalParent>;
} // 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_includes.hh b/src/model/solid_mechanics/materials/material_non_local_includes.hh
deleted file mode 100644
index 7966900c3..000000000
--- a/src/model/solid_mechanics/materials/material_non_local_includes.hh
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * 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_CMAKE_LIST_MATERIALS
-#include "material_marigo_non_local.hh"
-#include "material_mazars_non_local.hh"
-#include "material_von_mises_mazars_non_local.hh"
-#endif
-
-#define AKANTU_DAMAGE_NON_LOCAL_MATERIAL_LIST \
- ((2, (marigo_non_local, MaterialMarigoNonLocal)))( \
- (2, (mazars_non_local, MaterialMazarsNonLocal)))( \
- (2, (von_mises_mazars_non_local, MaterialVonMisesMazarsNonLocal)))
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 3cc5947a1..924af0122 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,88 +1,74 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialDruckerPrager<dim>::MaterialDruckerPrager(SolidMechanicsModel & model,
- const ID & id)
- : Parent(model, id) {
- this->initialize();
-}
-/* -------------------------------------------------------------------------- */
-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();
-}
-
-/* -------------------------------------------------------------------------- */
-template <Int dim> void MaterialDruckerPrager<dim>::initialize() {
+ const ID & id,
+ const ID & fe_engine_id)
+ : MaterialPlastic<dim>(model, id, fe_engine_id) {
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");
}
/* -------------------------------------------------------------------------- */
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 <Int dim>
void MaterialDruckerPrager<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
if (this->finite_deformation) {
AKANTU_TO_IMPLEMENT();
}
MaterialThermal<dim>::computeStress(el_type, ghost_type);
// infinitesimal and finite deformation
for (auto && args : Parent::getArguments(el_type, ghost_type)) {
computeStressOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
template class MaterialDruckerPrager<1>;
template class MaterialDruckerPrager<2>;
template class MaterialDruckerPrager<3>;
-static bool material_is_allocated_plastic_drucker_prager =
+const bool material_is_allocated_plastic_drucker_prager [[maybe_unused]] =
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 3837f2208..b4745d19e 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,109 +1,105 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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__
+#ifndef AKANTU_MATERIAL_DRUCKER_PRAGER_HH_
+#define AKANTU_MATERIAL_DRUCKER_PRAGER_HH_
namespace akantu {
/**
* Material plastic with a Drucker-pruger yield criterion
*/
template <Int dim> class MaterialDruckerPrager : public MaterialPlastic<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
using Parent = MaterialPlastic<dim>;
public:
- MaterialDruckerPrager(SolidMechanicsModel & model, const ID & id = "");
- MaterialDruckerPrager(SolidMechanicsModel & model, Int spatial_dimension,
- const Mesh & mesh, FEEngine & fe_engine,
- const ID & id = "");
+ MaterialDruckerPrager(SolidMechanicsModel & model, const ID & id = "",
+ const ID & fe_engine_id = "");
protected:
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;
protected:
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);
/// 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 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__ */
+#endif /*AKANTU_MATERIAL_DRUCKER_PRAGER_HH_ */
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 0466a53bb..19057c93d 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,90 +1,87 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
void MaterialLinearIsotropicHardening<dim>::computeStress(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
// NOLINTNEXTLINE(bugprone-parent-virtual-call)
- MaterialThermal<dim>::computeStress(el_type, ghost_type);
+ Parent::computeStress(el_type, ghost_type);
if (this->finite_deformation) { // Finite deformation
- for (auto && data :
+ for (auto && [args, green_strain] :
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);
+ make_view<dim, dim>((*this->green_strain)(el_type, ghost_type)))) {
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);
+ auto previous_green_strain = Material::gradUToE<dim>(previous_grad_u);
+ auto 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 <Int spatial_dimension>
void MaterialLinearIsotropicHardening<spatial_dimension>::computeTangentModuli(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
for (auto && args :
Parent::getArgumentsTangent(tangent_matrix, el_type, ghost_type)) {
computeTangentModuliOnQuad(args);
}
this->was_stiffness_assembled = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template class MaterialLinearIsotropicHardening<1>;
template class MaterialLinearIsotropicHardening<2>;
template class MaterialLinearIsotropicHardening<3>;
-static bool material_is_allocated_plastic_linear_isotropic_hardening =
- instantiateMaterial<MaterialLinearIsotropicHardening>(
+const bool material_is_allocated_plastic_linear_isotropic_hardening
+ [[maybe_unused]] = instantiateMaterial<MaterialLinearIsotropicHardening>(
"plastic_linear_isotropic_hardening");
} // 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 44352489c..e25e4ff97 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.cc
@@ -1,148 +1,110 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 <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 <Int spatial_dimension>
-void MaterialPlastic<spatial_dimension>::initialize() {
+template <Int dim>
+MaterialPlastic<dim>::MaterialPlastic(SolidMechanicsModel & model,
+ const ID & id, const ID & fe_engine_id)
+ : MaterialElastic<dim>(model, id, fe_engine_id),
+ iso_hardening(this->registerInternal("iso_hardening", 1)),
+ inelastic_strain(this->registerInternal("inelastic_strain", dim * dim)),
+ plastic_energy(this->registerInternal("plastic_energy", 1)),
+ d_plastic_energy(this->registerInternal("d_plastic_energy", 1)) {
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->inelastic_strain.initialize(spatial_dimension * spatial_dimension);
this->inelastic_strain.initializeHistory();
}
/* -------------------------------------------------------------------------- */
-template <Int spatial_dimension>
-Real MaterialPlastic<spatial_dimension>::getEnergy(const std::string & type) {
+template <Int dim>
+Real MaterialPlastic<dim>::getEnergy(const std::string & type) {
if (type == "plastic") {
return getPlasticEnergy();
}
- return MaterialElastic<spatial_dimension>::getEnergy(type);
+ return MaterialElastic<dim>::getEnergy(type);
}
/* -------------------------------------------------------------------------- */
-template <Int spatial_dimension>
-Real MaterialPlastic<spatial_dimension>::getPlasticEnergy() {
+template <Int dim> Real MaterialPlastic<dim>::getPlasticEnergy() {
AKANTU_DEBUG_IN();
+ auto & fem = this->getFEEngine();
Real penergy = 0.;
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));
+ this->getElementFilter().elementTypes(dim, _not_ghost)) {
+ penergy += fem.integrate(plastic_energy(type, _not_ghost), type, _not_ghost,
+ this->getElementFilter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return penergy;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialPlastic<dim>::computePotentialEnergy(ElementType el_type) {
- auto epot = this->potential_energy(el_type).begin();
-
- for (auto && args : getArguments(el_type)) {
+ for (auto && [args, epot] :
+ zip(getArguments(el_type), this->potential_energy(el_type))) {
Matrix<Real, dim, dim> elastic_strain =
args["grad_u"_n] - args["inelastic_strain"_n];
MaterialElastic<dim>::computePotentialEnergyOnQuad(
- tuple::replace(args, "grad_u"_n = elastic_strain), *epot);
+ tuple::replace(args, "grad_u"_n = elastic_strain), epot);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialPlastic<dim>::updateEnergies(ElementType el_type) {
MaterialElastic<dim>::updateEnergies(el_type);
for (auto && args : zip_append(getArguments(el_type),
"pe"_n = this->plastic_energy(el_type),
"wp"_n = this->d_plastic_energy(el_type))) {
- Matrix<Real, dim, dim> delta_strain_it =
+ Matrix<Real, dim, dim> delta_strain =
args["inelastic_strain"_n] - args["previous_inelastic_strain"_n];
Matrix<Real, dim, dim> sigma_h = args["sigma"_n] + args["previous_sigma"_n];
auto && wp = args["wp"_n];
- wp = .5 * sigma_h.doubleDot(delta_strain_it);
+ wp = sigma_h.doubleDot(delta_strain) / 2.;
args["pe"_n] += wp;
}
}
/* -------------------------------------------------------------------------- */
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 f5d204d58..e56c546df 100644
--- a/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
+++ b/src/model/solid_mechanics/materials/material_plastic/material_plastic.hh
@@ -1,146 +1,138 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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();
+ MaterialPlastic(SolidMechanicsModel & model, const ID & id = "",
+ const ID & fe_engine_id = "");
/* ------------------------------------------------------------------------ */
/* 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
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;
+ InternalField<Real> & iso_hardening;
/// inelastic strain arrays ordered by element types (inelastic deformation)
- InternalField<Real> inelastic_strain;
+ InternalField<Real> & inelastic_strain;
/// Plastic energy
- InternalField<Real> 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;
+ InternalField<Real> & d_plastic_energy;
};
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
} // namespace akantu
#endif /* AKANTU_MATERIAL_PLASTIC_HH_ */
diff --git a/src/model/solid_mechanics/materials/material_thermal.cc b/src/model/solid_mechanics/materials/material_thermal.cc
index 189e32a3b..beaeb1bb0 100644
--- a/src/model/solid_mechanics/materials/material_thermal.cc
+++ b/src/model/solid_mechanics/materials/material_thermal.cc
@@ -1,84 +1,61 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialThermal<dim>::MaterialThermal(SolidMechanicsModel & model,
- const ID & id)
- : Material(model, id), delta_T("delta_T", *this),
- sigma_th("sigma_th", *this) {
- this->initialize();
-}
-
-/* -------------------------------------------------------------------------- */
-template <Int dim>
-MaterialThermal<dim>::MaterialThermal(SolidMechanicsModel & model,
- 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) {
- this->initialize();
-}
+ const ID & id, const ID & fe_engine_id)
+ : Material(model, id, fe_engine_id),
+ delta_T(this->registerInternal("delta_T", 1)),
+ sigma_th(this->registerInternal("sigma_th", 1)) {
+ sigma_th.initializeHistory();
-/* -------------------------------------------------------------------------- */
-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 <Int dim> void MaterialThermal<dim>::initMaterial() {
- sigma_th.initialize(1);
- sigma_th.initializeHistory();
-
- Material::initMaterial();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialThermal<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
auto && arguments = getArguments(el_type, ghost_type);
for (auto && args : arguments) {
computeStressOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
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 d379d9935..4ef974180 100644
--- a/src/model/solid_mechanics/materials/material_thermal.hh
+++ b/src/model/solid_mechanics/materials/material_thermal.hh
@@ -1,115 +1,107 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim> class MaterialThermal : public Material {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- MaterialThermal(SolidMechanicsModel & model, const ID & id = "");
- MaterialThermal(SolidMechanicsModel & model, Int spatial_dimension,
- const Mesh & mesh, FEEngine & fe_engine, const ID & id = "");
-
- ~MaterialThermal() override = default;
-
-protected:
- void initialize();
+ MaterialThermal(SolidMechanicsModel & model, const ID & id = "",
+ const ID & fe_engine_id = "");
/* ------------------------------------------------------------------------ */
/* 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
template <class Args> inline void computeStressOnQuad(Args && args);
/* ------------------------------------------------------------------------ */
+ template <Int dim_ = dim>
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)));
+ return zip_append(Material::getArguments<dim_>(el_type, ghost_type),
+ "delta_T"_n = delta_T(el_type, ghost_type),
+ "sigma_th"_n = sigma_th(el_type, ghost_type),
+ "previous_sigma_th"_n =
+ sigma_th.previous(el_type, ghost_type));
}
+ template <Int dim_ = dim>
decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrices,
ElementType el_type,
GhostType ghost_type) {
- return Material::getArgumentsTangent<dim>(tangent_matrices, el_type,
- ghost_type);
+ return Material::getArgumentsTangent<dim_>(tangent_matrices, el_type,
+ ghost_type);
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// Young modulus
- Real E;
+ Real E{0.};
/// Poisson ratio
- Real nu;
+ Real nu{1. / 2.};
/// Thermal expansion coefficient
/// TODO : implement alpha as a matrix
- Real alpha;
+ Real alpha{0.};
/// Temperature field
- InternalField<Real> delta_T;
+ InternalField<Real> & delta_T;
/// Current thermal stress
- InternalField<Real> sigma_th;
+ InternalField<Real> & sigma_th;
};
/* ------------------------------------------------------------------------ */
/* Inline impl */
/* ------------------------------------------------------------------------ */
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 <>
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 01f92f133..a7951837c 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,240 +1,210 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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();
-
+ : MaterialElastic<dim>(model, id),
+ stress_dev(this->registerInternal("stress_dev", dim * dim)),
+ history_integral(this->registerInternal("history_integral", dim * dim)),
+ dissipated_energy(this->registerInternal("dissipated_energy", 1)) {
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");
-
- 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 <Int dim>
-void MaterialStandardLinearSolidDeviatoric<dim>::initMaterial() {
- AKANTU_DEBUG_IN();
-
- updateInternalParameters();
- MaterialElastic<dim>::initMaterial();
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::updateInternalParameters() {
MaterialElastic<dim>::updateInternalParameters();
E_inf = this->E - this->Ev;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::setToSteadyState(
ElementType el_type, GhostType ghost_type) {
/// Loop on all quadrature points
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();
dev_s = 2 * this->mu *
((grad_u + grad_u.transpose()) / 2. -
Theta * Matrix<Real, dim, dim>::Identity() / 3.);
h.zero();
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::computeStress(
ElementType el_type, GhostType ghost_type) {
Real tau = eta / Ev;
- Real dt = this->model.getTimeStep();
+ Real dt = this->getModel().getTimeStep();
Real exp_dt_tau = exp(-dt / tau);
Real exp_dt_tau_2 = exp(-.5 * dt / tau);
- Matrix<Real, dim, dim> s;
- Matrix<Real, dim, dim> epsilon_d;
- Matrix<Real, dim, dim> U_rond_prim;
-
/// Compute the first invariant of strain
auto gamma_inf = E_inf / this->E;
auto gamma_v = Ev / this->E;
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];
- s.zero();
- sigma.zero();
-
- epsilon_d = this->template gradUToEpsilon<dim>(grad_u);
+ auto epsilon_d = this->template gradUToEpsilon<dim>(grad_u);
auto Theta = epsilon_d.trace();
epsilon_d -= Matrix<Real, dim, dim>::Identity() * Theta / 3.;
- U_rond_prim =
+ auto U_rond_prim =
Matrix<Real, dim, dim>::Identity() * gamma_inf * this->kpa * Theta;
- s = 2 * this->mu * epsilon_d;
+ auto 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);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialStandardLinearSolidDeviatoric<dim>::updateDissipatedEnergy(
ElementType el_type, GhostType ghost_type) {
Real tau = eta / Ev;
- Matrix<Real, dim, dim> q;
- Matrix<Real, dim, dim> q_rate;
- Matrix<Real, dim, dim> epsilon_d;
-
- auto dt = this->model.getTimeStep();
+ auto dt = this->getModel().getTimeStep();
auto gamma_v = Ev / this->E;
auto alpha = 1. / (2. * this->mu * gamma_v);
- 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);
+ for (auto && [args, dis_energy] :
+ zip(this->getArguments(el_type, ghost_type),
+ dissipated_energy(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
- epsilon_d = Material::gradUToEpsilon<dim>(grad_u);
+ auto epsilon_d = Material::gradUToEpsilon<dim>(grad_u);
auto Theta = epsilon_d.trace();
epsilon_d -= Matrix<Real, dim, dim>::Identity() * Theta / 3.;
- q = (dev_s - h) * gamma_v;
- q_rate = (dev_s * gamma_v - q) / tau;
+ auto q = (dev_s - h) * gamma_v;
+ auto q_rate = (dev_s * gamma_v - q) / tau;
dis_energy += ((epsilon_d - alpha * q) * q_rate * dt).sum();
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getDissipatedEnergy() const {
AKANTU_DEBUG_IN();
+ auto & fem = this->getFEEngine();
Real de = 0.;
/// integrate the dissipated energy for each type of elements
- 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));
+ for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+ de += fem.integrate(dissipated_energy(type, _not_ghost), type, _not_ghost,
+ this->getElementFilter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return de;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getDissipatedEnergy(
const Element & element) const {
AKANTU_DEBUG_IN();
- auto nb_quadrature_points = this->fem.getNbIntegrationPoints(element.type);
- auto it = this->dissipated_energy(element.type, _not_ghost)
- .begin(nb_quadrature_points);
+ auto & fem = this->getFEEngine();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(element.type);
+ auto it = make_view(dissipated_energy(element.type, _not_ghost),
+ nb_quadrature_points)
+ .begin();
AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[element.element], element);
+ return fem.integrate(it[element.element], element);
}
/* -------------------------------------------------------------------------- */
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 <Int dim>
Real MaterialStandardLinearSolidDeviatoric<dim>::getEnergy(
const std::string & energy_id, const Element & element) {
if (energy_id == "dissipated") {
return getDissipatedEnergy(element);
}
if (energy_id == "dissipated_sls_deviatoric") {
return getDissipatedEnergy(element);
}
return Parent::getEnergy(energy_id, element);
}
/* -------------------------------------------------------------------------- */
template class MaterialStandardLinearSolidDeviatoric<1>;
template class MaterialStandardLinearSolidDeviatoric<2>;
template class MaterialStandardLinearSolidDeviatoric<3>;
-static bool material_is_allocated_sls_deviatoric =
+const bool material_is_allocated_sls_deviatoric [[maybe_unused]] =
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 c8a3738cf..57758c0ce 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,132 +1,130 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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(const Element & element) const;
+ [[nodiscard]] Real getDissipatedEnergy() const;
+ [[nodiscard]] 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,
- const Element & element) override;
+ [[nodiscard]] Real getEnergy(const std::string & type) override;
+ [[nodiscard]] Real getEnergy(const std::string & energy_id,
+ const Element & element) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// viscosity, viscous elastic modulus
- Real eta, Ev, E_inf;
+ Real eta{0.};
+ Real Ev{0.};
+ Real E_inf{0.};
Vector<Real> etas;
/// history of deviatoric stress
- InternalField<Real> stress_dev;
+ InternalField<Real> & stress_dev;
/// Internal variable: history integral
- InternalField<Real> history_integral;
+ InternalField<Real> & history_integral;
/// Dissipated energy
- InternalField<Real> 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 81727b083..b8eca48b8 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,617 +1,503 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialViscoelasticMaxwell<dim>::MaterialViscoelasticMaxwell(
SolidMechanicsModel & model, const ID & id)
- : 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();
-
+ : MaterialElastic<dim>(model, id),
+ dissipated_energy(this->registerInternal("dissipated_energy", 1)),
+ mechanical_work(this->registerInternal("mechanical_work", 1)) {
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->dissipated_energy.initialize(1);
- this->mechanical_work.initialize(1);
-
- AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim> void MaterialViscoelasticMaxwell<dim>::initMaterial() {
AKANTU_DEBUG_IN();
this->E = Einf + Ev.lpNorm<1>();
- // this->E = std::min(this->Einf, this->Ev(0));
+
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 = dim * dim;
- this->sigma_v.initialize(stress_size * this->Ev.size());
- this->epsilon_v.initialize(stress_size * this->Ev.size());
+ auto stress_size = dim * dim;
+ this->registerInternal("sigma_v", stress_size * this->Ev.size());
+ this->registerInternal("epsilon_v", stress_size * this->Ev.size());
+
+ this->sigma_v = this->getSharedPtrInternal("sigma_v");
+ this->epsilon_v = this->getSharedPtrInternal("epsilon_v");
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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 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 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 <Int dim>
void MaterialViscoelasticMaxwell<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
- AKANTU_DEBUG_IN();
-
// NOLINTNEXTLINE(bugprone-parent-virtual-call)
- MaterialThermal<dim>::computeStress(el_type, ghost_type);
-
- auto sigma_th_it = this->sigma_th(el_type, ghost_type).begin();
-
- auto previous_gradu_it =
- make_view<dim, dim>(this->gradu.previous(el_type, ghost_type)).begin();
-
- auto previous_stress_it =
- make_view<dim, dim>(this->stress.previous(el_type, ghost_type)).begin();
-
- auto sigma_v_it =
- 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;
+ Parent::computeStress(el_type, ghost_type);
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
-
- AKANTU_DEBUG_OUT();
+ for (auto && args : getArguments(el_type, ghost_type)) {
+ computeStressOnQuad(args);
+ }
}
/* -------------------------------------------------------------------------- */
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();
+template <class Args>
+void MaterialViscoelasticMaxwell<dim>::computeStressOnQuad(Args && args) {
+ Real dt = this->getModel().getTimeStep();
// Wikipedia convention:
// 2*eps_ij (i!=j) = voigt_eps_I
// http://en.wikipedia.org/wiki/Voigt_notation
- auto voigt_current_strain =
- Material::strainToVoigt<dim>(Material::gradUToEpsilon<dim>(grad_u));
+ auto voigt_current_strain = Material::strainToVoigt<dim>(
+ Material::gradUToEpsilon<dim>(args["grad_u"_n]));
auto voigt_previous_strain = Material::strainToVoigt<dim>(
- Material::gradUToEpsilon<dim>(previous_grad_u));
+ Material::gradUToEpsilon<dim>(args["previous_grad_u"_n]));
Vector<Real, voigt_h::size> voigt_stress =
this->Einf * this->C * voigt_current_strain;
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)) {
+ for (auto && [Eta, Ev, sigma] : zip(this->Eta, this->Ev, args["sigma_v"_n])) {
auto lambda = Eta / Ev;
auto exp_dt_lambda = exp(-dt / lambda);
- Real E_additional;
+ Real E_additional{0.};
if (exp_dt_lambda == 1) {
E_additional = Ev;
} else {
E_additional = (1 - exp_dt_lambda) * Ev * lambda / dt;
}
voigt_stress += E_additional * stress +
exp_dt_lambda * Material::stressToVoigt<dim>(sigma);
}
+ auto && sigma = args["sigma"_n];
for (Int I = 0; I < voigt_h::size; ++I) {
- auto i = voigt_h::vec[I][0];
- auto j = voigt_h::vec[I][1];
-
+ auto && [i, j] = voigt_h::vec[I];
sigma(i, j) = sigma(j, i) =
- voigt_stress(I) + Math::kronecker(i, j) * sigma_th;
+ voigt_stress(I) + Math::kronecker(i, j) * args["sigma_th"_n];
}
}
/* -------------------------------------------------------------------------- */
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(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();
+ for (auto && [args, epot, epsilon_v] :
+ zip(getArguments(el_type), this->potential_energy(el_type),
+ make_view((*this->epsilon_v)(el_type), dim, dim, Eta.size()))) {
+ this->computePotentialEnergyOnQuad(args["grad_u"_n], epot,
+ args["sigma_v"_n], epsilon_v);
+ }
}
/* -------------------------------------------------------------------------- */
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;
epot = 0.5 * voigt_stress.dot(voigt_strain);
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);
+ epot += sigma_v(k).doubleDot(epsilon_v(k)) / 2.;
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialViscoelasticMaxwell<dim>::afterSolveStep(bool converged) {
Material::afterSolveStep(converged);
if (not converged) {
return;
}
- 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(dim, dim);
-
- auto sigma_v_it =
- 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(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;
+ if (this->update_variable_flag) {
+ updateIntVariables();
+ }
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
- }
+ for (const auto & el_type : this->getElementFilter().elementTypes(
+ _all_dimensions, _not_ghost, _ek_not_defined)) {
this->updateDissipatedEnergy(el_type);
}
}
/* -------------------------------------------------------------------------- */
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, dim, dim> grad_delta_u = grad_u - previous_grad_u;
- Real dt = this->model.getTimeStep();
+ Real dt = this->getModel().getTimeStep();
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;
+ Real E_ef_v = this->Ev(k);
- if (exp_dt_lambda == 1) {
- E_ef_v = this->Ev(k);
- } else {
- E_ef_v = (1 - exp_dt_lambda) * this->Ev(k) * lambda / dt;
+ if (exp_dt_lambda != 1) {
+ E_ef_v *= (1 - exp_dt_lambda) * lambda / dt;
}
auto voigt_sigma_v = Material::stressToVoigt<dim>(sigma_v(k));
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 (Int I = 0; I < voigt_h::size; ++I) {
- auto i = voigt_h::vec[I][0];
- auto j = voigt_h::vec[I][1];
+ auto && [i, j] = voigt_h::vec[I];
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 <Int dim>
void MaterialViscoelasticMaxwell<dim>::computeTangentModuli(
- ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
+ ElementType /*el_type*/, Array<Real> & tangent_matrix,
+ GhostType /*ghost_type*/) {
AKANTU_DEBUG_IN();
- Real dt = this->model.getTimeStep();
+ Real dt = this->getModel().getTimeStep();
Real E_ef = this->Einf;
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;
+ const auto tangent_size = Material::getTangentStiffnessVoigtSize(dim);
+ for (auto && tangent :
+ make_view<tangent_size, tangent_size>(tangent_matrix)) {
+ this->computeTangentModuliOnQuad(tangent);
+ }
tangent_matrix *= E_ef;
this->was_stiffness_assembled = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <typename D1>
void MaterialViscoelasticMaxwell<dim>::computeTangentModuliOnQuad(
Eigen::MatrixBase<D1> & tangent) {
tangent = C;
}
/* -------------------------------------------------------------------------- */
template <Int dim> void MaterialViscoelasticMaxwell<dim>::updateIntVariables() {
- for (const 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(dim, dim);
-
- auto sigma_v_it =
- 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(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;
+ for (const auto & el_type : this->getElementFilter().elementTypes()) {
+ for (auto && [args, epsilon_v] :
+ zip(getArguments(el_type),
+ make_view((*this->epsilon_v)(el_type), dim, dim, Eta.size()))) {
- MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END;
+ updateIntVarOnQuad(args["grad_u"_n], args["previous_grad_u"_n],
+ args["sigma_v"_n], epsilon_v);
+ }
}
}
/* -------------------------------------------------------------------------- */
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(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();
+ for (auto && [args, epot, edis, work] :
+ zip(getArguments(el_type), this->potential_energy(el_type),
+ this->dissipated_energy(el_type), this->mechanical_work(el_type))) {
+ updateDissipatedEnergyOnQuad(args["grad_u"_n], args["previous_grad_u"_n],
+ args["sigma"_n], args["previous_sigma"_n],
+ edis, work, epot);
+ }
}
/* -------------------------------------------------------------------------- */
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->getModel().getTimeStep();
- 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;
+ auto && strain_rate = (grad_u - previous_grad_u) / dt;
+ auto && av_stress = (sigma + previous_sigma) / 2.;
mech_work += av_stress.doubleDot(strain_rate) * dt;
dis_energy = mech_work - pot_energy;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getDissipatedEnergy() const {
AKANTU_DEBUG_IN();
+ auto & fem = this->getFEEngine();
Real de = 0.;
/// integrate the dissipated energy for each type of elements
- 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));
+ for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+ de += fem.integrate(this->dissipated_energy(type, _not_ghost), type,
+ _not_ghost, this->getElementFilter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return de;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getDissipatedEnergy(
const Element & element) const {
- AKANTU_DEBUG_IN();
-
- 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);
+ auto & fem = this->getFEEngine();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(element.type);
+ auto it =
+ make_view(this->dissipated_energy(element.type), nb_quadrature_points)
+ .begin();
+ auto mat_element = element;
+ mat_element.element = this->getElementFilter()(element);
- AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[element.element],
- {element.type, gindex, _not_ghost});
+ return fem.integrate(it[element.element], mat_element);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getMechanicalWork() const {
- AKANTU_DEBUG_IN();
-
+ auto & fem = this->getFEEngine();
Real mw = 0.;
/// integrate the dissipated energy for each type of elements
- 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));
+ for (auto && type : this->getElementFilter().elementTypes(dim)) {
+ mw += fem.integrate(this->mechanical_work(type), type, _not_ghost,
+ this->getElementFilter(type, _not_ghost));
}
- AKANTU_DEBUG_OUT();
return mw;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getMechanicalWork(
const Element & element) const {
- AKANTU_DEBUG_IN();
+ auto & fem = this->getFEEngine();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(element.type);
+ auto it = make_view(this->mechanical_work(element.type), nb_quadrature_points)
+ .begin();
- 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);
+ auto mat_element = element;
+ mat_element.element = this->getElementFilter()(element);
- AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[element.element],
- {element.type, gindex, _not_ghost});
+ return fem.integrate(it[element.element], mat_element);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getPotentialEnergy() const {
AKANTU_DEBUG_IN();
+ auto & fem = this->getFEEngine();
Real epot = 0.;
/// integrate the dissipated energy for each type of elements
- 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));
+ for (auto && type : this->getElementFilter().elementTypes(dim, _not_ghost)) {
+ epot += fem.integrate(this->potential_energy(type, _not_ghost), type,
+ _not_ghost, this->getElementFilter(type, _not_ghost));
}
AKANTU_DEBUG_OUT();
return epot;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getPotentialEnergy(
const Element & element) const {
AKANTU_DEBUG_IN();
- 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);
+ auto & fem = this->getFEEngine();
+ auto nb_quadrature_points = fem.getNbIntegrationPoints(element.type);
+ auto it =
+ make_view(this->potential_energy(element.type), nb_quadrature_points)
+ .begin();
+ auto mat_element = element;
+ mat_element.element = this->getElementFilter()(element);
AKANTU_DEBUG_OUT();
- return this->fem.integrate(it[element.element],
- {element.type, gindex, _not_ghost});
+ return fem.integrate(it[element.element], mat_element);
}
/* -------------------------------------------------------------------------- */
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<dim>::getEnergy(type);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
Real MaterialViscoelasticMaxwell<dim>::getEnergy(const std::string & energy_id,
const Element & element) {
if (energy_id == "dissipated") {
return getDissipatedEnergy(element);
}
if (energy_id == "potential") {
return getPotentialEnergy(element);
}
if (energy_id == "work") {
return getMechanicalWork(element);
}
return MaterialElastic<dim>::getEnergy(energy_id, element);
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialViscoelasticMaxwell<dim>::forceUpdateVariable() {
update_variable_flag = true;
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialViscoelasticMaxwell<dim>::forceNotUpdateVariable() {
update_variable_flag = false;
}
/* -------------------------------------------------------------------------- */
-template class MaterialViscoelasticMaxwell<1>;
-template class MaterialViscoelasticMaxwell<2>;
-template class MaterialViscoelasticMaxwell<3>;
-static bool material_is_allocated_viscoelastic_maxwell =
+const bool material_is_allocated_viscoelastic_maxwell [[maybe_unused]] =
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 24be41fdd..08e581793 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,216 +1,220 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
class MaterialViscoelasticMaxwell : public MaterialElastic<dim> {
+ using Parent = 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
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;
/// 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:
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);
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
- 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);
+ template <class Args> void computeStressOnQuad(Args && args);
/// compute tangent moduli on a quadrature point
template <typename D1>
void computeTangentModuliOnQuad(Eigen::MatrixBase<D1> & tangent);
bool hasStiffnessMatrixChanged() override {
- Real dt = this->model.getTimeStep();
+ Real dt = this->getModel().getTimeStep();
return ((this->previous_dt == dt)
? (!(this->previous_dt == dt)) * (this->was_stiffness_assembled)
: (!(this->previous_dt == dt)));
// return (!(this->previous_dt == dt));
}
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(MaterialElastic<dim>::getArguments(el_type, ghost_type),
+ "sigma_v"_n = make_view((*sigma_v)(el_type, ghost_type),
+ dim, dim, Ev.size()));
+ }
+
MatrixType getTangentType() override { return _symmetric; }
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// give the dissipated energy
- Real getDissipatedEnergy() const;
- Real getDissipatedEnergy(const Element & element) const;
+ [[nodiscard]] Real getDissipatedEnergy() const;
+ [[nodiscard]] Real getDissipatedEnergy(const Element & element) const;
/// get the potential energy
- Real getPotentialEnergy() const;
- Real getPotentialEnergy(const Element & element) const;
+ [[nodiscard]] Real getPotentialEnergy() const;
+ [[nodiscard]] Real getPotentialEnergy(const Element & element) const;
/// get the potential energy
- Real getMechanicalWork() const;
- Real getMechanicalWork(const Element & element) const;
+ [[nodiscard]] Real getMechanicalWork() const;
+ [[nodiscard]] 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,
- const Element & element) override;
+ [[nodiscard]] Real getEnergy(const std::string & type) override;
+ [[nodiscard]] Real getEnergy(const std::string & energy_id,
+ const Element & element) override;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
using voigt_h = VoigtHelper<dim>;
/// Vectors of viscosity, viscous elastic modulus, one spring element elastic
/// modulus
Vector<Real> Eta;
Vector<Real> Ev;
- Real Einf;
+
+ Real Einf{0.};
/// time step from previous solveStep
- Real previous_dt;
+ Real previous_dt{0.};
/// Stiffness matrix template
- Matrix<Real> C;
+ Matrix<Real, voigt_h::size, voigt_h::size> C;
/// Compliance matrix template
- Matrix<Real> D;
+ Matrix<Real, voigt_h::size, voigt_h::size> D;
/// Internal variable: viscous_stress
- InternalField<Real> sigma_v;
+ std::shared_ptr<InternalField<Real>> sigma_v;
/// Internal variable: spring strain in Maxwell element
- InternalField<Real> epsilon_v;
+ std::shared_ptr<InternalField<Real>> epsilon_v;
/// Dissipated energy
- InternalField<Real> dissipated_energy;
+ InternalField<Real> & dissipated_energy;
/// Mechanical work
- InternalField<Real> mechanical_work;
+ InternalField<Real> & mechanical_work;
/// Update internal variable after solve step or not
- bool update_variable_flag;
+ bool update_variable_flag{true};
};
} // 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 57fab3e60..575deaf33 100644
--- a/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
+++ b/src/model/solid_mechanics/materials/plane_stress_toolbox.hh
@@ -1,93 +1,99 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim, class ParentMaterial = Material>
class PlaneStressToolbox : public ParentMaterial {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "")
- : ParentMaterial(model, id) {}
- 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;
+ PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "",
+ const ID & fe_engine_id = "")
+ : ParentMaterial(model, id, fe_engine_id) {}
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*/) {}
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ ParentMaterial::template getArguments<dim>(el_type, ghost_type),
+ "C33"_n = broadcast(C33, this->stress(el_type, ghost_type).size()));
+ }
+
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrix,
+ ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ ParentMaterial::template getArgumentsTangent<dim>(tangent_matrix,
+ el_type, ghost_type),
+ "C33"_n = broadcast(C33, this->stress(el_type, ghost_type).size()));
+ }
+
protected:
- bool initialize_third_axis_deformation{false};
+ Real C33{1.};
};
#define AKANTU_PLANE_STRESS_TOOL_SPEC(dim) \
template <> \
inline PlaneStressToolbox<dim, Material>::PlaneStressToolbox( \
- SolidMechanicsModel & model, const ID & id) \
- : Material(model, id) {}
+ SolidMechanicsModel & model, const ID & id, const ID & fe_engine_id) \
+ : Material(model, id, fe_engine_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 c0ba4cd3f..dcdd7ea58 100644
--- a/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
+++ b/src/model/solid_mechanics/materials/plane_stress_toolbox_tmpl.hh
@@ -1,156 +1,129 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
-
+/* -------------------------------------------------------------------------- */
+#include "plane_stress_toolbox.hh"
/* -------------------------------------------------------------------------- */
#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, Int dim, const Mesh & mesh,
- FEEngine & fe_engine, const ID & id = "");
-
- ~PlaneStressToolbox() override = default;
+ PlaneStressToolbox(SolidMechanicsModel & model, const ID & id = "",
+ const ID & fe_engine_id = "");
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");
+ this->third_axis_deformation.setDefaultValue(1.);
}
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- /* ------------------------------------------------------------------------ */
- void initMaterial() override {
+ decltype(auto) getArguments(ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(
+ ParentMaterial::template getArguments<2>(el_type, ghost_type),
+ "C33"_n = third_axis_deformation(el_type, ghost_type));
+ }
- ParentMaterial::initMaterial();
- if (this->plane_stress && this->initialize_third_axis_deformation) {
- this->third_axis_deformation.initialize(1);
- this->third_axis_deformation.resize();
- }
+ decltype(auto) getArgumentsTangent(Array<Real> & tangent_matrix,
+ ElementType el_type,
+ GhostType ghost_type = _not_ghost) {
+ return zip_append(ParentMaterial::template getArgumentsTangent<2>(
+ tangent_matrix, el_type, ghost_type),
+ "C33"_n = third_axis_deformation(el_type, ghost_type));
}
/* ------------------------------------------------------------------------ */
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->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){};
+ computeCauchyStressPlaneStress(ElementType /*el_type*/,
+ GhostType /*ghost_type*/ = _not_ghost){};
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// third axis strain measure value
- InternalField<Real> third_axis_deformation;
+ 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;
+ bool plane_stress{false};
};
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)
+ SolidMechanicsModel & model, const ID & id, const ID & fe_engine_id)
+ : ParentMaterial(model, id, fe_engine_id),
+ third_axis_deformation(
+ this->registerInternal("third_axis_deformation", 1)) {
this->initialize();
}
-template <class ParentMaterial>
-inline PlaneStressToolbox<2, ParentMaterial>::PlaneStressToolbox(
- 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/remove_damaged_weight_function_inline_impl.hh b/src/model/solid_mechanics/materials/weight_functions/remove_damaged_weight_function_inline_impl.hh
index 998a7d4ef..e186a2e7a 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,95 +1,93 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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) {
+inline Real
+RemoveDamagedWeightFunction::operator()(Real r, const IntegrationPoint & q1,
+ const IntegrationPoint & q2) {
/// compute the weight
- UInt quad = q2.global_num;
+ auto 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.;
+ auto & dam_array = (*this->damage)(q2.type, q2.ghost_type);
+ auto D = dam_array(quad);
+
if (D < damage_limit * (1 - Math::getTolerance())) {
Real alpha = std::max(0., 1. - r * r / this->R2);
- w = alpha * alpha;
+ return alpha * alpha;
}
- return w;
+ return 0.;
}
/* -------------------------------------------------------------------------- */
inline void RemoveDamagedWeightFunction::init() {
this->damage = &(this->manager.registerWeightFunctionInternal("damage"));
}
/* -------------------------------------------------------------------------- */
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());
+ *damage, buffer, elements, 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());
+ *damage, buffer, elements, this->manager.getModel().getFEEngine());
}
}
} // namespace akantu
#endif /* AKANTU_REMOVE_DAMAGED_WEIGHT_FUNCTION_INLINE_IMPL_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model.cc b/src/model/solid_mechanics/solid_mechanics_model.cc
index 54bab8a18..21737ca8d 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model.cc
@@ -1,1233 +1,1014 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "dumpable_inline_impl.hh" // NOLINT(unused-includes)
/* -------------------------------------------------------------------------- */
#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, 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) {
+ const std::shared_ptr<DOFManager> & dof_manager, const ModelType model_type)
+ : CLHParent(mesh, model_type, dim, 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::_smm_gradu);
this->registerSynchronizer(synchronizer, SynchronizationTag::_for_dump);
}
+ this->parser_type = ParserType::_material;
+
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);
}
+/* -------------------------------------------------------------------------- */
+void SolidMechanicsModel::instantiateMaterials() {}
+
/* -------------------------------------------------------------------------- */
/* 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 = -1, _with_nb_element = true);
- material_local_numbering.initialize(mesh, _element_kind = _ek_not_defined,
- _with_nb_element = true);
+ CLHParent::initFullImpl(options);
- Model::initFullImpl(options);
-
- // initialize the materials
- if (not this->parser.getLastParsedFile().empty()) {
- this->instantiateMaterials();
- this->initMaterials();
- }
+ // // initialize the materials
+ // if (not this->parser.getLastParsedFile().empty()) {
+ // this->instantiateMaterials();
+ // this->initConstitutiveLaws();
+ // }
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));
- }
+ for_each_constitutive_law([&](auto && material) {
+ 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();
- }
+ for_each_constitutive_law(
+ [&](auto && material) { material.beforeSolveStep(); });
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::afterSolveStep(bool converged) {
- for (auto & material : materials) {
- material->afterSolveStep(converged);
- }
+ for_each_constitutive_law(
+ [&](auto && material) { 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);
- }
+ for_each_constitutive_law(
+ [](auto && material) { material.computeAllStresses(_not_ghost); });
/* ------------------------------------------------------------------------ */
/* Computation of the non local part */
- if (this->non_local_manager) {
- this->non_local_manager->computeAllNonLocalStresses();
+ if (this->isNonLocal()) {
+ this->getNonLocalManager().computeAllNonLocalContribution();
}
// 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);
- }
+ for_each_constitutive_law(
+ [](auto && material) { 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);
- }
+ for_each_constitutive_law(
+ [](auto && material) { 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");
- }
+ for_each_constitutive_law([&](auto && material) {
+ 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);
- }
+ for_each_constitutive_law(
+ [](auto && material) { 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());
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;
+ Element elem{_not_defined, 0, ghost_type};
elem.ghost_type = ghost_type;
for (auto type :
mesh.elementTypes(Model::spatial_dimension, ghost_type, _ek_regular)) {
elem.type = type;
auto nb_nodes_per_element = mesh.getNbNodesPerElement(type);
+ auto mat_indexes = this->getConstitutiveLawByElement(type, ghost_type);
+ auto mat_loc_num = this->getConstitutiveLawLocalNumbering(type, ghost_type);
+
Array<Real> X(0, nb_nodes_per_element * Model::spatial_dimension);
FEEngine::extractNodalToElementField(mesh, *current_position, X, type,
_not_ghost);
- for (auto && data :
+ for (auto && [X_el, mat_idx, el] :
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);
-
- auto el_h = getFEEngine().getElementInradius(X_el, type);
- auto el_c = this->materials[mat_idx]->getCelerity(elem);
+ make_view(mat_indexes), make_view(mat_loc_num))) {
+ elem.element = el;
+
+ auto el_h = FEEngine::getElementInradius(X_el, type);
+ auto el_c = this->getMaterial(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.;
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 (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 (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;
+ return ekin / 2.;
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getKineticEnergy(const Element & element) {
AKANTU_DEBUG_IN();
auto nb_quadrature_points =
getFEEngine().getNbIntegrationPoints(element.type);
Array<Real> vel_on_quad(nb_quadrature_points, 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 = getConstitutiveLaw(element).getRho();
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, element);
}
/* -------------------------------------------------------------------------- */
Real SolidMechanicsModel::getExternalWork() {
AKANTU_DEBUG_IN();
- Array<Real> * incrs_or_velos;
+ Array<Real> * incrs_or_velos{nullptr};
if (this->method == _static) {
incrs_or_velos = this->displacement_increment.get();
} else {
incrs_or_velos = this->velocity.get();
}
Real work = 0.;
auto nb_nodes = this->mesh.getNbNodes();
- for (auto && data :
+ for (auto && [ext_force, int_force, boun, incr_or_velo, n] :
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);
-
auto is_local_node = this->mesh.isLocalOrMasterNode(n);
// bool is_not_pbc_slave_node = !this->isPBCSlaveNode(n);
auto count_node = is_local_node; // && is_not_pbc_slave_node;
if (count_node) {
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);
- }
+ for_each_constitutive_law(
+ [&](auto && material) { 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,
const Element & element) {
AKANTU_DEBUG_IN();
if (energy_id == "kinetic") {
return getKineticEnergy(element);
}
- 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});
+ auto mat_element = element;
+ mat_element.element = this->getConstitutiveLawLocalNumbering()(element);
+
+ Real energy =
+ this->getConstitutiveLaw(element).getEnergy(energy_id, mat_element);
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 = -1);
- this->material_local_numbering.initialize(
- mesh, _element_kind = _ek_not_defined, _with_nb_element = true,
- _default_value = -1);
-
- 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<Idx> & new_numbering,
- const RemovedElementsEvent & event) {
- for (auto & material : materials) {
- material->onElementsRemoved(element_list, new_numbering, event);
- }
-}
-
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::onNodesAdded(const Array<Idx> & nodes_list,
const NewNodesEvent & event) {
AKANTU_DEBUG_IN();
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);
- }
+ for_each_constitutive_law(
+ [&](auto && material) { material.onNodesAdded(nodes_list, event); });
need_to_reassemble_lumped_mass = true;
need_to_reassemble_mass = true;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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 << "Solid Mechanics Model ["
+ << "\n";
+ stream << space << " + id : " << id << "\n";
stream << space << " + spatial dimension : " << Model::spatial_dimension
- << std::endl;
+ << "\n";
- stream << space << " + fem [" << std::endl;
+ stream << space << " + fem ["
+ << "\n";
getFEEngine().printself(stream, indent + 2);
- stream << space << " ]" << std::endl;
+ stream << space << " ]"
+ << "\n";
- stream << space << " + nodals information [" << std::endl;
+ stream << space << " + nodals information ["
+ << "\n";
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) {
- if (not aka::is_of_type<MaterialNonLocalInterface>(mat)) {
- continue;
- }
-
- auto && mat_non_local = dynamic_cast<MaterialNonLocalInterface &>(*mat);
+ stream << space << " ]"
+ << "\n";
- 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);
+ stream << space << " + materials ["
+ << "\n";
+ this->for_each_constitutive_law(
+ [&](auto && material) { material.printself(stream, indent + 2); });
+ stream << space << " ]"
+ << "\n";
- 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.insertIntegrationPointsInNeighborhoods(
- ghost_type, quadrature_points_coordinates);
- }
+ stream << space << "]"
+ << "\n";
}
/* -------------------------------------------------------------------------- */
-void SolidMechanicsModel::computeNonLocalStresses(GhostType ghost_type) {
- for (auto & mat : materials) {
- if (not aka::is_of_type<MaterialNonLocalInterface>(*mat)) {
- continue;
+void SolidMechanicsModel::computeNonLocalContribution(GhostType ghost_type) {
+ for_each_constitutive_law([&](auto && material) {
+ if (aka::is_of_type<MaterialNonLocalInterface>(material)) {
+ auto & mat_non_local =
+ dynamic_cast<MaterialNonLocalInterface &>(material);
+ mat_non_local.computeNonLocalStresses(ghost_type);
}
-
- 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);
- }
-}
-
/* -------------------------------------------------------------------------- */
Int SolidMechanicsModel::getNbData(const Array<Element> & elements,
const SynchronizationTag & tag) const {
- AKANTU_DEBUG_IN();
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(decltype(material_index)::value_type);
- break;
- }
case SynchronizationTag::_smm_mass: {
- size += nb_nodes_per_element * sizeof(Real) *
- Model::spatial_dimension; // mass vector
+ size += spatial_dimension * nb_nodes_per_element * Int(sizeof(Real));
break;
}
case SynchronizationTag::_smm_for_gradu: {
- size += nb_nodes_per_element * Model::spatial_dimension *
- sizeof(Real); // displacement
+ size += spatial_dimension * nb_nodes_per_element * Int(sizeof(Real));
break;
}
- case SynchronizationTag::_smm_boundary: {
- // force, displacement, boundary
- size += nb_nodes_per_element * Model::spatial_dimension *
- (2 * sizeof(Real) + sizeof(bool));
+ case SynchronizationTag::_for_dump: {
+ size += 5 * spatial_dimension * nb_nodes_per_element * Int(sizeof(Real));
break;
}
- case SynchronizationTag::_for_dump: {
- // displacement, velocity, acceleration, residual, force
- size += nb_nodes_per_element * Model::spatial_dimension * sizeof(Real) * 5;
+ case SynchronizationTag::_smm_boundary: {
+ size += 3 * spatial_dimension * nb_nodes_per_element * Int(sizeof(Real));
break;
}
default: {
}
}
- if (tag != SynchronizationTag::_material_id) {
- splitByMaterial(elements, [&](auto && mat, auto && elements) {
- size += mat.getNbData(elements, tag);
- });
- }
-
- AKANTU_DEBUG_OUT();
+ size += CLHParent::getNbData(elements, tag);
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);
- });
- }
+ CLHParent::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) {
- decltype(material_index)::value_type recv_mat_index;
- buffer >> recv_mat_index;
- auto & mat_index = material_index(element);
- if (mat_index != -1) {
- continue;
- }
-
- // add ghosts element to the correct material
- mat_index = recv_mat_index;
- 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();
+ CLHParent::unpackData(buffer, elements, tag);
}
-/* -------------------------------------------------------------------------- */
+/* --------------------------------------------------------------------------
+ */
Int SolidMechanicsModel::getNbData(const Array<Idx> & dofs,
const SynchronizationTag & tag) const {
- AKANTU_DEBUG_IN();
-
Int size = 0;
switch (tag) {
case SynchronizationTag::_smm_uv: {
- size += sizeof(Real) * Model::spatial_dimension * 2;
+ size += Int(sizeof(Real)) * Model::spatial_dimension * 2;
break;
}
case SynchronizationTag::_smm_res: /* FALLTHRU */
case SynchronizationTag::_smm_mass: {
- size += sizeof(Real) * Model::spatial_dimension;
+ size += Int(sizeof(Real)) * Model::spatial_dimension;
break;
}
case SynchronizationTag::_for_dump: {
- size += sizeof(Real) * Model::spatial_dimension * 5;
+ size += Int(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<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<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();
}
+/* --------------------------------------------------------------------------
+ */
+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_each_constitutive_law([&](auto && material) {
+ if (material.getName() == material_name) {
+ material.applyEigenGradU(prescribed_eigen_grad_u, ghost_type);
+ }
+ });
+}
+
+/* --------------------------------------------------------------------------
+ */
+void SolidMechanicsModel::registerNewMaterial(const ID & mat_name,
+ const ID & mat_type,
+ const ID & opt_param) {
+ this->registerNewConstitutiveLaw(mat_name, mat_type, opt_param);
+}
+
+/* --------------------------------------------------------------------------
+ */
+
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model.hh b/src/model/solid_mechanics/solid_mechanics_model.hh
index 586cd9b73..d922e44ad 100644
--- a/src/model/solid_mechanics/solid_mechanics_model.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model.hh
@@ -1,588 +1,489 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "constitutive_laws_handler.hh"
#include "fe_engine.hh"
+#include "material.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 ConstitutiveLawSelector;
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<Idx>,
+ : public ConstitutiveLawsHandler<Material, Model>,
public BoundaryCondition<SolidMechanicsModel>,
- public NonLocalManagerCallback,
public EventHandlerManager<SolidMechanicsModelEventHandler> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- class NewMaterialElementsEvent : public NewElementsEvent {
- public:
- AKANTU_GET_MACRO_NOT_CONST(MaterialList, material, Array<Int> &);
- AKANTU_GET_MACRO(MaterialList, material, const Array<Int> &);
-
- protected:
- Array<Int> material;
- };
-
using MyFEEngineType = FEEngineTemplate<IntegratorGauss, ShapeLagrange>;
protected:
using EventManager = EventHandlerManager<SolidMechanicsModelEventHandler>;
+ using CLHParent = ConstitutiveLawsHandler<Material, Model>;
public:
SolidMechanicsModel(Mesh & mesh, Int dim = _all_dimensions,
const ID & id = "solid_mechanics_model",
- std::shared_ptr<DOFManager> dof_manager = nullptr,
+ const 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;
+ void instantiateMaterials();
+public:
/// 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>
+ [[nodiscard]] 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; }
+ [[nodiscard]] bool canSplitResidual() const override { return true; }
/// get the type of matrix needed
- MatrixType getMatrixType(const ID & matrix_id) const override;
+ [[nodiscard]] 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;
+public:
/* ------------------------------------------------------------------------ */
- ModelSolverOptions
+ [[nodiscard]] TimeStepSolverType getDefaultSolverType() const override;
+
+ [[nodiscard]] 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<Idx> * filter = nullptr);
+ void computeNonLocalContribution(GhostType ghost_type) override;
/* ------------------------------------------------------------------------ */
/* 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);
+ /* ------------------------------------------------------------------------ */
+ /* Energies */
+ /* ------------------------------------------------------------------------ */
+protected:
/// compute the kinetic energy
Real getKineticEnergy();
[[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;
+public:
+ /// get the energies
+ Real getEnergy(const std::string & energy_id);
- void insertIntegrationPointsInNeighborhoods(GhostType ghost_type) override;
+ /// compute the energy for an element
+ [[deprecated("Use the interface with an Element")]] Real
+ getEnergy(const std::string & energy_id, ElementType type, Idx index) {
+ return getEnergy(energy_id, Element{type, index, _not_ghost});
+ };
- /// update the values of the non local internal
- void updateLocalInternal(ElementTypeMapReal & internal_flat,
- GhostType ghost_type, ElementKind kind) override;
+ /// compute the energy for an element
+ Real getEnergy(const std::string & energy_id, const Element & element);
- /// copy the results of the averaging in the materials
- void updateNonLocalInternal(ElementTypeMapReal & internal_flat,
- GhostType ghost_type, ElementKind kind) override;
+ /// compute the energy for an element group
+ Real getEnergy(const ID & energy_id, const ID & group_id);
/* ------------------------------------------------------------------------ */
/* Data Accessor inherited members */
/* ------------------------------------------------------------------------ */
public:
- Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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;
- Int getNbData(const Array<Idx> & dofs,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] Int getNbData(const Array<Idx> & dofs,
+ const SynchronizationTag & tag) const override;
void packData(CommunicationBuffer & buffer, const Array<Idx> & dofs,
const SynchronizationTag & tag) const override;
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<Idx> & nodes_list,
const NewNodesEvent & event) override;
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<Idx> & new_numbering,
- const RemovedElementsEvent & event) 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<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,
Int spatial_dimension, ElementKind kind) override;
void dump(const std::string & dumper_name) 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(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::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();
+ inline decltype(auto) getMaterials() { return this->getConstitutiveLaws(); }
/// get an iterable on the materials
- inline decltype(auto) getMaterials() const;
+ [[nodiscard]] inline decltype(auto) getMaterials() const {
+ return this->getConstitutiveLaws();
+ }
/// get a particular material (by numerical material index)
- inline Material & getMaterial(UInt mat_index);
+ inline Material & getMaterial(Idx mat_index) {
+ return this->getConstitutiveLaw(mat_index);
+ }
/// get a particular material (by numerical material index)
- inline const Material & getMaterial(UInt mat_index) const;
+ [[nodiscard]] inline const Material & getMaterial(Idx mat_index) const {
+ return this->getConstitutiveLaw(mat_index);
+ }
/// get a particular material (by material name)
- inline Material & getMaterial(const std::string & name);
+ inline Material & getMaterial(const std::string & name) {
+ return this->getConstitutiveLaw(name);
+ }
/// get a particular material (by material name)
- inline const Material & getMaterial(const std::string & name) const;
+ [[nodiscard]] inline const Material &
+ getMaterial(const std::string & name) const {
+ return this->getConstitutiveLaw(name);
+ }
/// get a particular material (by material name)
- inline const Material & getMaterial(const Element & element) const;
+ [[nodiscard]] inline const Material &
+ getMaterial(const Element & element) const {
+ return this->getConstitutiveLaw(element);
+ }
/// get a particular material id from is name
- inline Int getMaterialIndex(const std::string & name) const;
+ [[nodiscard]] inline auto getMaterialIndex(const std::string & name) const {
+ return this->getConstitutiveLawIndex(name);
+ }
/// give the number of materials
- inline Int getNbMaterials() const { return materials.size(); }
+ [[nodiscard]] inline auto getNbMaterials() const {
+ return this->getNbConstitutiveLaws();
+ }
- /// give the material internal index from its id
- Int getInternalIndexFromID(const ID & id) const;
+ void reassignMaterial() { this->reassignConstitutiveLaw(); }
+ void registerNewMaterial(const ID & mat_name, const ID & mat_type,
+ const ID & opt_param);
/// 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);
+ // this function is kept for backward compatinility
+ [[nodiscard]] decltype(auto) getMaterialByElement() const {
+ return this->getConstitutiveLawByElement();
+ }
- /// compute the energy for one element
- Real getEnergy(const std::string & energy_id, const Element & element);
+ // this function is kept for backward compatinility
+ [[nodiscard]] decltype(auto) getMaterialLocalNumbering() const {
+ return this->getConstitutiveLawLocalNumbering();
+ }
- [[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});
+ // this function is kept for backward compatinility
+ [[nodiscard]] decltype(auto)
+ getMaterialByElement(ElementType type,
+ GhostType ghost_type = _not_ghost) const {
+ return this->getConstitutiveLawByElement(type, ghost_type);
}
- /// Compute energy for an element group
- Real getEnergy(const ID & energy_id, const ID & group_id);
+ // this function is kept for backward compatinility
+ [[nodiscard]] decltype(auto)
+ getMaterialLocalNumbering(ElementType type,
+ GhostType ghost_type = _not_ghost) const {
+ return this->getConstitutiveLawLocalNumbering(type, ghost_type);
+ }
- 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,
- Int);
- // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(MaterialByElement, material_index, Int);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(MaterialLocalNumbering,
- 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);
+ // this function is kept for backward compatinility
+ decltype(auto) getMaterialSelector() {
+ return this->getConstitutiveLawSelector();
}
- /// Access the non_local_manager interface
- AKANTU_GET_MACRO(NonLocalManager, *non_local_manager, NonLocalManager &);
+ // this function is kept for backward compatinility
+ void setMaterialSelector(
+ const std::shared_ptr<ConstitutiveLawSelector> & material_selector) {
+ this->setConstitutiveLawSelector(material_selector);
+ }
/// 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
Int displacement_release{0};
/// release version of the current_position array
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, 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<Int> material_index;
-
- /// Arrays containing the position in the element filter of the material
- /// (material's 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 "material_selector_tmpl.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/material_selector_cohesive.cc b/src/model/solid_mechanics/solid_mechanics_model_cohesive/material_selector_cohesive.cc
index 2be04c9de..66af8418d 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,153 +1,169 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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()) {
+ : model(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());
+ this->setFallback(
+ std::make_shared<DefaultMaterialSelector>(model.getMaterialByElement()));
+
+ this->setFallbackCohesiveValue(getDefaultCohesiveMaterial(model));
+}
+
+/* -------------------------------------------------------------------------- */
+Int DefaultMaterialCohesiveSelector::getDefaultCohesiveMaterial(
+ const SolidMechanicsModelCohesive & model) {
+ for (auto && [id, mat] : enumerate(model.getConstitutiveLaws())) {
+ if (aka::is_of_type<MaterialCohesive>(mat)) {
+ return Int(id);
+ }
+ }
+ return -1;
}
/* -------------------------------------------------------------------------- */
Int DefaultMaterialCohesiveSelector::operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_cohesive) {
+ if (this->getFallbackCohesiveValue() == -1) {
+ this->setFallbackCohesiveValue(getDefaultCohesiveMaterial(this->model));
+ }
+
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));
+ cohesive_el_to_facet(element.element, Int(third_dimension));
if (facet_material.exists(facet.type, facet.ghost_type)) {
return facet_material(facet.type, facet.ghost_type)(facet.element);
}
- return fallback_value;
+
+ return this->getFallbackCohesiveValue();
} catch (...) {
- return fallback_value;
+ return this->getFallbackCohesiveValue();
}
} else if (Mesh::getSpatialDimension(element.type) ==
mesh.getSpatialDimension() - 1) {
return facet_material(element.type, element.ghost_type)(element.element);
} else {
- return MaterialSelector::operator()(element);
+ return ConstitutiveLawSelector::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);
+ : DefaultMaterialCohesiveSelector(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);
+ this->setFallback(std::make_shared<MeshDataMaterialSelector<std::string>>(
+ "physical_names", model));
}
/* -------------------------------------------------------------------------- */
Int MeshDataMaterialCohesiveSelector::operator()(const Element & element) {
if (Mesh::getKind(element.type) == _ek_cohesive or
Mesh::getSpatialDimension(element.type) ==
mesh_facets.getSpatialDimension() - 1) {
- Element facet;
+ Element facet{ElementNull};
if (Mesh::getKind(element.type) == _ek_cohesive) {
facet =
mesh_facets.getSubelementToElement(element.type, element.ghost_type)(
- element.element, UInt(third_dimension));
+ element.element, Int(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 DefaultMaterialCohesiveSelector::operator()(element);
}
}
- return MaterialSelector::operator()(element);
+ return DefaultMaterialCohesiveSelector::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()),
+ : DefaultMaterialCohesiveSelector(model),
+ mesh_data_id(std::move(mesh_data_id)), mesh_facets(model.getMeshFacets()),
spatial_dimension(model.getSpatialDimension()), rules(rules) {
// cohesive fallback
- this->fallback_selector =
- std::make_shared<DefaultMaterialCohesiveSelector>(model);
+ this->setFallback(std::make_shared<DefaultMaterialCohesiveSelector>(model));
// non cohesive fallback
- this->fallback_selector->setFallback(
+ this->getFallbackSelector()->setFallback(
std::make_shared<MeshDataMaterialSelector<std::string>>(
this->mesh_data_id, model));
}
/* -------------------------------------------------------------------------- */
Int MaterialCohesiveRulesSelector::operator()(const Element & element) {
if (mesh_facets.getSpatialDimension(element.type) ==
(spatial_dimension - 1)) {
- const auto & element_to_subelement = mesh_facets.getElementToSubelement(
- element.type, element.ghost_type)(element.element);
+ const auto & element_to_subelement =
+ mesh_facets.getElementToSubelement(element);
const auto & el1 = element_to_subelement[0];
const auto & el2 = element_to_subelement[1];
- auto id1 = mesh.getData<std::string>(mesh_data_id, el1.type,
- el1.ghost_type)(el1.element);
+ auto id1 = this->mesh.getData<std::string>(mesh_data_id, el1);
auto id2 = id1;
if (el2 != ElementNull) {
- id2 = mesh.getData<std::string>(mesh_data_id, el2.type,
- el2.ghost_type)(el2.element);
+ id2 = this->mesh.getData<std::string>(mesh_data_id, el2);
}
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);
+ return ConstitutiveLawSelector::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 a0865a105..a59ec0e83 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,87 +1,92 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
+class DefaultMaterialCohesiveSelector : public ConstitutiveLawSelector {
public:
DefaultMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model);
Int operator()(const Element & element) override;
-private:
+ AKANTU_SET_MACRO(FallbackCohesiveValue, default_cohesive_value, Int);
+ AKANTU_GET_MACRO(FallbackCohesiveValue, default_cohesive_value, Int);
+ static Int
+ getDefaultCohesiveMaterial(const SolidMechanicsModelCohesive & model);
+
+protected:
+ const SolidMechanicsModelCohesive & model;
const ElementTypeMapArray<Idx> & facet_material;
const Mesh & mesh;
+ Int default_cohesive_value;
};
/* -------------------------------------------------------------------------- */
/// To be used with intrinsic elements inserted along mesh physical surfaces
-class MeshDataMaterialCohesiveSelector : public MaterialSelector {
+class MeshDataMaterialCohesiveSelector
+ : public DefaultMaterialCohesiveSelector {
public:
MeshDataMaterialCohesiveSelector(const SolidMechanicsModelCohesive & model);
Int operator()(const Element & element) override;
-protected:
- const SolidMechanicsModelCohesive & model;
+private:
const Mesh & mesh_facets;
const ElementTypeMapArray<std::string> & material_index;
- bool third_dimension;
+ bool third_dimension{false};
};
/// bulk1, bulk2 -> cohesive
using MaterialCohesiveRules = std::map<std::pair<ID, ID>, ID>;
/* -------------------------------------------------------------------------- */
-class MaterialCohesiveRulesSelector : public MaterialSelector {
+class MaterialCohesiveRulesSelector : public DefaultMaterialCohesiveSelector {
public:
MaterialCohesiveRulesSelector(const SolidMechanicsModelCohesive & model,
const MaterialCohesiveRules & rules,
ID mesh_data_id = "physical_names");
Int operator()(const Element & element) override;
private:
- const SolidMechanicsModelCohesive & model;
ID mesh_data_id;
- const Mesh & mesh;
const Mesh & mesh_facets;
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/cohesive_internal_field.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field.hh
index eaa4e2ef1..c6df001d7 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field.hh
@@ -1,57 +1,77 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Akantu. If not, see <http://www.gnu.org/licenses/>.
*/
/* -------------------------------------------------------------------------- */
#include "internal_field.hh"
+#include "random_internal_field.hh"
#ifndef AKANTU_COHESIVE_INTERNAL_FIELD_HH_
#define AKANTU_COHESIVE_INTERNAL_FIELD_HH_
namespace akantu {
/// internal field class for cohesive materials
template <typename T> class CohesiveInternalField : public InternalField<T> {
public:
- CohesiveInternalField(const ID & id, Material & material);
- ~CohesiveInternalField() override;
+ CohesiveInternalField(const ID & id,
+ ConstitutiveLawInternalHandler & constitutive_law,
+ Int dim, const ID & fem_id,
+ const ElementTypeMapArray<Idx> & element_filter);
/// initialize the field to a given number of component
- void initialize(UInt nb_component) override;
+ void initialize(Int nb_component) override;
private:
- CohesiveInternalField operator=(__attribute__((unused))
- const CohesiveInternalField & other){};
+ friend class ConstitutiveLawInternalHandler;
+
+ CohesiveInternalField operator=(const CohesiveInternalField & /*other*/){};
};
/* -------------------------------------------------------------------------- */
/* Facet Internal Field */
/* -------------------------------------------------------------------------- */
template <typename T> class FacetInternalField : public InternalField<T> {
public:
- FacetInternalField(const ID & id, Material & material);
- ~FacetInternalField() override;
+ FacetInternalField(const ID & id,
+ ConstitutiveLawInternalHandler & constitutive_law, Int dim,
+ const ID & fem_id,
+ const ElementTypeMapArray<Idx> & element_filter);
+
+ std::shared_ptr<FacetInternalField> getPtr() {
+ return aka::as_type<FacetInternalField>(this->shared_from_this());
+ }
/// initialize the field to a given number of component
- void initialize(UInt nb_component) override;
+ void initialize(Int nb_component) override;
+
+ friend class ConstitutiveLawInternalHandler;
};
+template <typename T>
+using CohesiveRandomInternalField =
+ RandomInternalField<T, CohesiveInternalField, RandomGenerator>;
+
+template <typename T>
+using FacetRandomInternalField =
+ RandomInternalField<T, FacetInternalField, RandomGenerator>;
+
} // namespace akantu
#endif /* AKANTU_COHESIVE_INTERNAL_FIELD_HH_ */
diff --git a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh
index 7efea52aa..a7af30474 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh
+++ b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/cohesive_internal_field_tmpl.hh
@@ -1,84 +1,112 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* 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_COHESIVE_INTERNAL_FIELD_TMPL_HH_
#define AKANTU_COHESIVE_INTERNAL_FIELD_TMPL_HH_
namespace akantu {
+/* -------------------------------------------------------------------------- */
template <typename T>
-CohesiveInternalField<T>::CohesiveInternalField(const ID & id,
- Material & material)
- : InternalField<T>(
- id, material, material.getModel().getFEEngine("CohesiveFEEngine"),
- aka::as_type<MaterialCohesive>(material).getElementFilter()) {
+CohesiveInternalField<T>::CohesiveInternalField(
+ const ID & id, ConstitutiveLawInternalHandler & constitutive_law, Int dim,
+ const ID & fem_id, const ElementTypeMapArray<Idx> & element_filter)
+ : InternalField<T>(id, constitutive_law, dim, fem_id, element_filter) {
this->element_kind = _ek_cohesive;
}
template <typename T>
-CohesiveInternalField<T>::~CohesiveInternalField() = default;
-
-template <typename T>
-void CohesiveInternalField<T>::initialize(UInt nb_component) {
+void CohesiveInternalField<T>::initialize(Int nb_component) {
this->internalInitialize(nb_component);
}
+/* -------------------------------------------------------------------------- */
+template <>
+inline CohesiveInternalField<Real> &
+ConstitutiveLawInternalHandler::registerInternal<Real, CohesiveInternalField>(
+ const ID & id, Int nb_component) {
+ return this->registerInternal<Real, CohesiveInternalField>(
+ id, nb_component, "CohesiveFEEngine");
+}
+/* -------------------------------------------------------------------------- */
+template <>
+inline CohesiveRandomInternalField<Real> &
+ConstitutiveLawInternalHandler::registerInternal<
+ Real, CohesiveRandomInternalField>(const ID & id, Int nb_component) {
+ return this->registerInternal<Real, CohesiveRandomInternalField>(
+ id, nb_component, "CohesiveFEEngine");
+}
+
/* -------------------------------------------------------------------------- */
template <typename T>
-FacetInternalField<T>::FacetInternalField(const ID & id, Material & material)
- : InternalField<T>(
- id, material, material.getModel().getFEEngine("FacetsFEEngine"),
- aka::as_type<MaterialCohesive>(material).getFacetFilter()) {
+FacetInternalField<T>::FacetInternalField(
+ const ID & id, ConstitutiveLawInternalHandler & constitutive_law, Int dim,
+ const ID & fem_id, const ElementTypeMapArray<Idx> & element_filter)
+ : InternalField<T>(id, constitutive_law, dim, fem_id, element_filter) {
this->spatial_dimension -= 1;
this->element_kind = _ek_regular;
}
-template <typename T> FacetInternalField<T>::~FacetInternalField() = default;
-
-template <typename T>
-void FacetInternalField<T>::initialize(UInt nb_component) {
+template <typename T> void FacetInternalField<T>::initialize(Int nb_component) {
this->internalInitialize(nb_component);
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-ParameterTyped<RandomInternalField<Real, FacetInternalField>>::setAuto(
+inline FacetInternalField<Real> &
+ConstitutiveLawInternalHandler::registerInternal<Real, FacetInternalField>(
+ const ID & id, Int nb_component) {
+ return this->registerInternal<Real, FacetInternalField>(
+ id, nb_component, "FacetsFEEngine",
+ aka::as_type<MaterialCohesive>(*this).getFacetFilter());
+}
+/* -------------------------------------------------------------------------- */
+template <>
+inline FacetRandomInternalField<Real> &
+ConstitutiveLawInternalHandler::registerInternal<
+ Real, FacetRandomInternalField>(const ID & id, Int nb_component) {
+ return this->registerInternal<Real, FacetRandomInternalField>(
+ id, nb_component, "FacetsFEEngine",
+ aka::as_type<MaterialCohesive>(*this).getFacetFilter());
+}
+
+/* -------------------------------------------------------------------------- */
+template <>
+inline void ParameterTyped<FacetRandomInternalField<Real>>::setAuto(
const ParserParameter & in_param) {
Parameter::setAuto(in_param);
RandomParameter<Real> r = in_param;
param.setRandomDistribution(r);
}
/* -------------------------------------------------------------------------- */
template <>
-inline void
-ParameterTyped<RandomInternalField<Real, CohesiveInternalField>>::setAuto(
+inline void ParameterTyped<CohesiveRandomInternalField<Real>>::setAuto(
const ParserParameter & in_param) {
Parameter::setAuto(in_param);
RandomParameter<Real> r = in_param;
param.setRandomDistribution(r);
}
} // namespace akantu
#endif /* AKANTU_COHESIVE_INTERNAL_FIELD_TMPL_HH_ */
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 f3dabc886..f1c0730a1 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,198 +1,198 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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"
+// #include "solid_mechanics_model_cohesive.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
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 <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 <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;
}
for (auto && el : element_list) {
// filter not ghost cohesive elements
if ((el.ghost_type != _not_ghost) or
(Mesh::getKind(el.type) != _ek_cohesive)) {
continue;
}
auto index = el.element;
auto type = el.type;
auto nb_quad_per_element = this->fem_cohesive.getNbIntegrationPoints(type);
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 =
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, 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 (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 <Int spatial_dimension>
template <typename D1>
void MaterialCohesiveBilinear<spatial_dimension>::scaleTraction(
const Element & el, Eigen::MatrixBase<D1> & sigma_c_vec) {
AKANTU_DEBUG_IN();
auto base_sigma_c = Real(this->sigma_c_eff);
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 auto & coh_element_to_facet = coh_element_to_facet_begin[el.element];
// compute bounding volume
Real volume = 0.;
// loop over facets
for (Int f = 0; f < 2; ++f) {
const auto & facet = coh_element_to_facet(f);
const auto & facet_to_element =
mesh_facets.getElementToSubelement(facet.type, facet.ghost_type);
// loop over elements connected to each facet
for (auto && elem : facet_to_element(facet.element)) {
// skip cohesive elements and dummy elements
if (elem == ElementNull || Mesh::getKind(elem.type) == _ek_cohesive) {
continue;
}
// unit vector for integration in order to obtain the volume
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);
}
}
// scale 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 <Int spatial_dimension>
void MaterialCohesiveBilinear<spatial_dimension>::computeTraction(
ElementType el_type, GhostType ghost_type) {
AKANTU_DEBUG_IN();
MaterialCohesiveLinear<spatial_dimension>::computeTraction(el_type,
ghost_type);
// adjust damage
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.));
}
}
/* -------------------------------------------------------------------------- */
template class MaterialCohesiveBilinear<1>;
template class MaterialCohesiveBilinear<2>;
template class MaterialCohesiveBilinear<3>;
-static bool material_is_alocated_cohesive_bilinear =
+const bool material_is_alocated_cohesive_bilinear [[maybe_unused]] =
instantiateMaterial<MaterialCohesiveBilinear>("cohesive_bilinear");
} // namespace akantu
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 e800ee523..1e4d871f5 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,297 +1,297 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 <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 <Int dim>
void MaterialCohesiveExponential<dim>::computeTraction(ElementType el_type,
GhostType ghost_type) {
AKANTU_DEBUG_IN();
/// compute scalars
Real beta2 = beta * beta;
/// loop on each quadrature point
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.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 =
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())) {
auto && delta_s = opening - normal_opening;
delta = tangential_opening_norm * beta;
computeCoupledTraction(traction, normal, delta, delta_s, delta_max,
delta_max_prev);
computeCompressiveTraction(traction, normal, normal_opening_norm,
opening);
} else
computeCoupledTraction(traction, normal, delta, opening, delta_max,
delta_max_prev);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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();
return;
}
/// 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 <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 <Int dim>
void MaterialCohesiveExponential<dim>::computeTangentTraction(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
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 (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.dot(normal);
auto && normal_opening = normal * normal_opening_norm;
auto && tangential_opening = opening - normal_opening;
Real tangential_opening_norm = tangential_opening.norm();
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())) {
auto && delta_s = opening - normal_opening;
delta = tangential_opening_norm * beta;
computeCoupledTangent(tangent, normal, delta, delta_s, delta_max_prev);
computeCompressivePenalty(tangent, normal, normal_opening_norm);
} else
computeCoupledTangent(tangent, normal, delta, opening, delta_max_prev);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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();
auto beta2 = beta * beta;
auto J = Matrix<Real, dim, dim>::Identity() * beta2;
if (std::abs(delta) < Math::getTolerance()) {
delta = Math::getTolerance();
}
auto opening_normal = opening.dot(normal);
auto && delta_e = normal * opening_normal * (1. - beta2) + beta2 * opening;
auto exponent = std::exp(1. - delta / delta_c) * sigma_c / delta_c;
auto && first_term = normal * normal.transpose() * (1. - beta2) + J;
auto && second_term = delta_e * delta_e.transpose() / delta / delta_c;
tangent = (first_term - second_term) * exponent;
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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 (not exp_penalty) {
delta_n = 0.;
}
auto && n_outer_n = normal * normal.transpose();
auto normal_tg = contact_tangent * std::exp(1.) * sigma_c *
std::exp(-delta_n / delta_c) * (1. - delta_n / delta_c) /
delta_c;
tangent = tangent + n_outer_n * normal_tg;
}
/* -------------------------------------------------------------------------- */
template class MaterialCohesiveExponential<1>;
template class MaterialCohesiveExponential<2>;
template class MaterialCohesiveExponential<3>;
-static bool material_is_alocated_cohesive_exponential =
+const bool material_is_alocated_cohesive_exponential [[maybe_unused]] =
instantiateMaterial<MaterialCohesiveExponential>("cohesive_exponential");
} // namespace akantu
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 778cadfde..6076666f2 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,334 +1,335 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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) {
+ : MaterialCohesive(model, id),
+ sigma_c_eff(registerInternal<Real, CohesiveRandomInternalField>(
+ "sigma_c_eff", 1)),
+ delta_c_eff(
+ registerInternal<Real, CohesiveInternalField>("delta_c_eff", 1)),
+ insertion_stress(registerInternal<Real, CohesiveInternalField>(
+ "insertion_stress", dim)) {
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 <Int dim> void MaterialCohesiveLinear<dim>::initMaterial() {
AKANTU_DEBUG_IN();
MaterialCohesive::initMaterial();
- sigma_c_eff.initialize(1);
- delta_c_eff.initialize(1);
- insertion_stress.initialize(dim);
-
if (not Math::are_float_equal(delta_c, 0.)) {
delta_c_eff.setDefaultValue(delta_c);
} else {
+ Real sigma_c = this->sigma_c;
delta_c_eff.setDefaultValue(2 * G_c / sigma_c);
}
if (model->getIsExtrinsic()) {
scaleInsertionTraction();
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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 <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 auto & mesh_facets = model->getMeshFacets();
const auto & fe_engine = model->getFEEngine();
const auto & fe_engine_facet = model->getFEEngine("FacetsFEEngine");
for (const auto & type_facet : mesh_facets.elementTypes(dim - 1)) {
const auto & facet_to_element =
mesh_facets.getElementToSubelement(type_facet);
auto nb_quad_per_facet = fe_engine_facet.getNbIntegrationPoints(type_facet);
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;
for (auto && elem : facet_to_element(f)) {
if (elem == ElementNull) {
continue;
}
// unit vector for integration in order to obtain the volume
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);
}
// scale 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 <Int dim>
+template <Int dim> // NOLINTNEXTLINE(readability-function-cognitive-complexity)
void MaterialCohesiveLinear<dim>::checkInsertion(bool check_only) {
AKANTU_DEBUG_IN();
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);
const auto & facets_check = inserter.getCheckFacets(type_facet);
auto & f_insertion = inserter.getInsertionFacets(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 & facet_filter_array = facet_filter(type_facet);
+ const auto & facet_filter_array = getFacetFilter(type_facet);
const auto & sigma_limit_array = sigma_c(type_facet);
auto nb_quad_facet =
model->getFEEngine("FacetsFEEngine").getNbIntegrationPoints(type_facet);
#ifndef AKANTU_NDEBUG
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
Matrix<Real, dim, dim> stress_tmp;
Matrix<Real> normal_traction(dim, nb_quad_facet);
Vector<Real> stress_check(nb_quad_facet);
const auto & tangents = model->getTangents(type_facet);
const auto & normals = model->getFEEngine("FacetsFEEngine")
.getNormalsOnIntegrationPoints(type_facet);
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 (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 (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
auto && stress_1 = facet_stress(0);
auto && stress_2 = facet_stress(1);
auto && stress_avg = (stress_1 + stress_2) / 2.;
// compute normal and effective stress
stress_check(q) = computeEffectiveNorm(stress_avg, normal, tangent,
normal_traction(q));
}
// verify if the effective stress overcomes the threshold
auto final_stress = stress_check.mean();
if (max_quad_stress_insertion) {
- final_stress = *std::max_element(stress_check.data(),
- stress_check.data() + nb_quad_facet);
+ final_stress =
+ *std::max_element(stress_check.begin(), stress_check.end());
}
if (final_stress > sigma_limit) {
f_insertion(facet) = true;
if (check_only) {
continue;
}
// store the new cohesive material parameters for each quadrature
// point
for (Int q = 0; q < nb_quad_facet; ++q) {
auto new_sigma = stress_check(q);
auto && normal_traction_vec = normal_traction(q);
if (dim != 3) {
normal_traction_vec *= -1.;
}
new_sigmas.push_back(new_sigma);
- new_normal_traction.push_back(normal_traction_vec);
+ new_normal_traction.emplace_back(normal_traction_vec);
- Real new_delta;
+ 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_limit / new_sigma * delta_c;
}
new_delta_c.push_back(new_delta);
}
}
}
// update material data for the new elements
auto old_nb_quad_points = sig_c_eff.size();
- Int new_nb_quad_points = new_sigmas.size();
+ Int new_nb_quad_points = Int(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 (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 (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 <Int dim>
void MaterialCohesiveLinear<dim>::computeTraction(ElementType el_type,
GhostType ghost_type) {
for (auto && args : getArguments(el_type, ghost_type)) {
this->computeTractionOnQuad(args);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialCohesiveLinear<dim>::computeTangentTraction(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
for (auto && [args, tangent] : zip(getArguments(el_type, ghost_type),
make_view<dim, dim>(tangent_matrix))) {
computeTangentTractionOnQuad(tangent, args);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template class MaterialCohesiveLinear<1>;
template class MaterialCohesiveLinear<2>;
template class MaterialCohesiveLinear<3>;
-static bool material_is_alocated_cohesive_linear =
+const bool material_is_alocated_cohesive_linear [[maybe_unused]] =
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 8047d5d99..2b7d9d677 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,180 +1,181 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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
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;
+ Real
+ computeEffectiveNorm(const Eigen::MatrixBase<D1> & stress,
+ const Eigen::MatrixBase<D2> & normal,
+ const Eigen::MatrixBase<D3> & tangent,
+ const Eigen::MatrixBase<D4> & normal_traction_) const;
protected:
/// constitutive law
void computeTraction(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute tangent stiffness matrix
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
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
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;
+ Real beta{};
/// beta square inverse to compute effective norm
- Real beta2_inv;
+ Real beta2_inv{};
/// mode I fracture energy
- Real G_c;
+ Real G_c{};
/// kappa parameter
- Real kappa;
+ Real kappa{};
/// constitutive law scalar to compute delta
- Real beta2_kappa2;
+ Real beta2_kappa2{};
/// constitutive law scalar to compute traction
- Real beta2_kappa;
+ Real beta2_kappa{};
/// penalty coefficient
- Real penalty;
+ Real penalty{};
/// reference volume used to scale sigma_c
- Real volume_s;
+ Real volume_s{};
/// weibull exponent used to scale sigma_c
- Real m_s;
+ Real m_s{};
/// variable defining if we are recomputing the last loading step
/// after load_reduction
- bool recompute;
+ bool recompute{};
/// critical effective stress
- RandomInternalField<Real, CohesiveInternalField> sigma_c_eff;
+ CohesiveRandomInternalField<Real> & sigma_c_eff;
/// effective critical displacement (each element can have a
/// different value)
- CohesiveInternalField<Real> delta_c_eff;
+ CohesiveInternalField<Real> & delta_c_eff;
/// stress at insertion
- CohesiveInternalField<Real> insertion_stress;
+ CohesiveInternalField<Real> & insertion_stress;
/// variable saying if there should be penalty contact also after
/// breaking the cohesive elements
- bool contact_after_breaking;
+ bool contact_after_breaking{};
/// insertion of cohesive element when stress is high enough just on
/// one quadrature point
- bool max_quad_stress_insertion;
+ 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 037249582..764e687c2 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,296 +1,303 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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) {
+ delta_prec(this->template registerInternal<Real, CohesiveInternalField>(
+ "delta_prec", 1)),
+ K_plus(this->template registerInternal<Real, CohesiveInternalField>(
+ "K_plus", 1)),
+ K_minus(this->template registerInternal<Real, CohesiveInternalField>(
+ "K_minus", 1)),
+ T_1d(this->template registerInternal<Real, CohesiveInternalField>("T_1d",
+ 1)),
+ normal_regime(
+ this->template registerInternal<bool, CohesiveInternalField>(
+ "normal_regime", 1)) {
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 <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);
+ this->template registerInternal<Int, CohesiveInternalField>("switches", 1);
+ switches = this->template getSharedPtrInternal<Int, CohesiveInternalField>(
+ "switches");
+ this->template registerInternal<Real, CohesiveInternalField>(
+ "delta_dot_prec", 1);
+ delta_dot_prec =
+ this->template getSharedPtrInternal<Real, CohesiveInternalField>(
+ "delta_dot_prec");
}
}
/* -------------------------------------------------------------------------- */
template <Int spatial_dimension>
void MaterialCohesiveLinearFatigue<spatial_dimension>::computeTraction(
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 = 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<Int> * 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);
+ switches_array = &(*switches)(el_type, ghost_type);
+ delta_dot_prec_array = &(*delta_dot_prec)(el_type, ghost_type);
}
Vector<Real, spatial_dimension> normal_opening;
Vector<Real, spatial_dimension> tangential_opening;
Real tolerance = Math::getTolerance();
/// loop on each quadrature point
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;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template class MaterialCohesiveLinearFatigue<1>;
template class MaterialCohesiveLinearFatigue<2>;
template class MaterialCohesiveLinearFatigue<3>;
-static bool material_is_alocated_cohesive_linear_fatigue =
+const bool material_is_alocated_cohesive_linear_fatigue [[maybe_unused]] =
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 a2efb4c9f..04e9ee8b8 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,121 +1,121 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get the switches
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Switches, switches, UInt);
+ AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Switches, (*switches), Int);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// delta_f parameter
- Real delta_f;
+ Real delta_f{-1.};
/// variable saying if delta_f is equal to delta_max for each
/// element when the traction is computed
- bool progressive_delta_f;
+ bool progressive_delta_f{false};
/// count the opening/closing switches per element
- bool count_switches;
+ bool count_switches{false};
/// delta of the previous step
- CohesiveInternalField<Real> delta_prec;
+ CohesiveInternalField<Real> & delta_prec;
/// stiffness for reloading
- CohesiveInternalField<Real> K_plus;
+ CohesiveInternalField<Real> & K_plus;
/// stiffness for unloading
- CohesiveInternalField<Real> K_minus;
+ CohesiveInternalField<Real> & K_minus;
/// 1D traction in the cohesive law
- CohesiveInternalField<Real> T_1d;
+ CohesiveInternalField<Real> & T_1d;
/// Number of opening/closing switches
- CohesiveInternalField<UInt> switches;
+ std::shared_ptr<CohesiveInternalField<Int>> switches;
/// delta increment of the previous time step
- CohesiveInternalField<Real> delta_dot_prec;
+ std::shared_ptr<CohesiveInternalField<Real>> delta_dot_prec;
/// has the element passed to normal regime (not in fatigue anymore)
- CohesiveInternalField<bool> normal_regime;
+ 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 e2ca1039e..cb29153fc 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,176 +1,169 @@
/**
* Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
MaterialCohesiveLinearFriction<dim>::MaterialCohesiveLinearFriction(
SolidMechanicsModel & model, const ID & id)
- : MaterialParent(model, id), residual_sliding("residual_sliding", *this),
- friction_force("friction_force", *this) {
+ : MaterialParent(model, id),
+ residual_sliding(
+ this->template registerInternal<Real, CohesiveInternalField>(
+ "residual_sliding", 1)),
+ friction_force(
+ this->template registerInternal<Real, CohesiveInternalField>(
+ "friction_force", dim)) {
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 <Int dim> void MaterialCohesiveLinearFriction<dim>::initMaterial() {
- AKANTU_DEBUG_IN();
-
- MaterialParent::initMaterial();
-
- friction_force.initialize(dim);
- residual_sliding.initialize(1);
residual_sliding.initializeHistory();
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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);
}
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));
}
for (auto && args : getArguments(el_type, ghost_type)) {
computeTractionOnQuad(args);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
template <Int dim>
void MaterialCohesiveLinearFriction<dim>::computeTangentTraction(
ElementType el_type, Array<Real> & tangent_matrix, GhostType ghost_type) {
AKANTU_DEBUG_IN();
for (auto && [args, tangent] : zip(getArguments(el_type, ghost_type),
make_view<dim, dim>(tangent_matrix))) {
this->computeTangentTractionOnQuad(tangent, args);
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();
}
/* -------------------------------------------------------------------------- */
template class MaterialCohesiveLinearFriction<1>;
template class MaterialCohesiveLinearFriction<2>;
template class MaterialCohesiveLinearFriction<3>;
-static bool material_is_allocated_cohesive_linear_friction =
+const bool material_is_allocated_cohesive_linear_friction [[maybe_unused]] =
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 7a2d08d47..15875c9c5 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,104 +1,100 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
class MaterialCohesiveLinearFriction : public MaterialCohesiveLinear<dim> {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
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(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute tangent stiffness matrix
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
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;
+ CohesiveInternalField<Real> & residual_sliding;
/// friction force
- CohesiveInternalField<Real> 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 41f557653..78de45f8c 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,252 +1,251 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "aka_static_if.hh"
+#include "material_cohesive_linear.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 <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 constexpr (dim == 2) {
Real tangent_contrib_tmp = normal_traction.dot(tangent);
tangent_contrib += tangent_contrib_tmp * tangent_contrib_tmp;
} 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 <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
auto norm = opening.dot(normal);
this->normal_opening_norm = norm;
this->normal_opening = normal * this->normal_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$
*/
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 < 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 = this->normal_opening * this->penalty;
contact_opening = this->normal_opening;
/// don't consider penetration contribution for delta
opening = tangential_opening;
this->normal_opening.zero();
} else {
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 {
AKANTU_DEBUG_ASSERT(delta_max != 0.,
"Division by zero, tolerance might be too low");
traction =
(this->tangential_opening * this->beta2_kappa + this->normal_opening) *
sigma_c / delta_max * (1. - damage);
}
}
/* -------------------------------------------------------------------------- */
template <Int dim>
template <class Derived, class Args>
inline void MaterialCohesiveLinear<dim>::computeTangentTractionOnQuad(
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
this->normal_opening_norm = opening.dot(normal);
this->normal_opening = normal * normal_opening_norm;
this->tangential_opening = opening - normal_opening;
this->tangential_opening_norm = tangential_opening.norm();
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;
auto && n_outer_n = normal * normal.transpose();
if (penetration) {
/// stiffness in compression given by the penalty parameter
tangent = penalty * (tangent + n_outer_n);
opening = tangential_opening;
normal_opening_norm = opening.dot(normal);
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.;
}
+ Real sigma_c = this->sigma_c;
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)
auto && I = Eigen::Matrix<Real, dim, dim>::Identity() * this->beta2_kappa;
auto && nn = (n_outer_n * (1. - this->beta2_kappa) + I) * t / delta;
auto && mm = opening * this->beta2_kappa2;
auto && t_tilde = normal_opening * (1. - this->beta2_kappa2) + mm;
auto && t_hat = normal_opening + this->beta2_kappa * tangential_opening;
auto && prov = t_hat * t_tilde.transpose() * derivative / delta + nn;
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 c846f65fb..86f359b36 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,375 +1,367 @@
/**
* Copyright (©) 2016-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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) {
+ : MaterialCohesiveLinear<dim>(model, id),
+ delta_n_max(this->template registerInternal<Real, CohesiveInternalField>(
+ "delta_n_max", 1)),
+ delta_t_max(this->template registerInternal<Real, CohesiveInternalField>(
+ "delta_t_max", 1)),
+ damage_n(this->template registerInternal<Real, CohesiveInternalField>(
+ "damage_n", 1)),
+ damage_t(this->template registerInternal<Real, CohesiveInternalField>(
+ "damage_t", 1)) {
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 <Int dim> void MaterialCohesiveLinearUncoupled<dim>::initMaterial() {
- AKANTU_DEBUG_IN();
-
- 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 <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(dim);
auto traction_end = this->tractions(el_type, ghost_type).end(dim);
auto opening_it = this->opening(el_type, ghost_type).begin(dim);
auto contact_traction_it =
this->contact_tractions(el_type, ghost_type).begin(dim);
auto contact_opening_it =
this->contact_opening(el_type, ghost_type).begin(dim);
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(dim);
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);
normal_opening = *normal_it * normal_opening_norm;
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 * 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, 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
AKANTU_DEBUG_ASSERT(*delta_n_max_it != 0.,
"Division by zero, tolerance might be too low");
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 {
AKANTU_DEBUG_ASSERT(*delta_t_max_it != 0.,
"Division by zero, tolerance might be too low");
shear_traction = tangential_opening * this->beta2_kappa * *sigma_c_it /
(*delta_t_max_it) * (1. - *damage_t_it);
}
*traction_it = normal_traction + shear_traction;
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
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(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(dim);
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);
normal_opening = *normal_it * normal_opening_norm;
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, 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 * 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, dim, dim> nn = n_outer_n * T / delta_n;
Vector<Real, dim> Delta_tilde =
normal_opening * (1. - this->beta2_kappa2) +
*opening_it * this->beta2_kappa2;
Matrix<Real, dim, dim> prov =
normal_opening * Delta_tilde.transpose() * derivative / delta_n + nn;
*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)
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();
}
/* -------------------------------------------------------------------------- */
template class MaterialCohesiveLinearUncoupled<1>;
template class MaterialCohesiveLinearUncoupled<2>;
template class MaterialCohesiveLinearUncoupled<3>;
-static bool material_is_allocated_cohesive_linear_uncoupled =
+const bool material_is_allocated_cohesive_linear_uncoupled [[maybe_unused]] =
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 73252f803..ed41e9823 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,88 +1,84 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// compute tangent stiffness matrix
void computeTangentTraction(ElementType el_type, Array<Real> & tangent_matrix,
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;
+ CohesiveInternalField<Real> & delta_n_max;
/// maximum tangential displacement
- CohesiveInternalField<Real> delta_t_max;
+ CohesiveInternalField<Real> & delta_t_max;
/// damage associated to normal tractions
- CohesiveInternalField<Real> damage_n;
+ CohesiveInternalField<Real> & damage_n;
/// damage associated to shear tractions
- CohesiveInternalField<Real> damage_t;
+ 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 43affa03c..7e8776ea8 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,504 +1,481 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "sparse_matrix.hh"
/* -------------------------------------------------------------------------- */
namespace akantu {
/* -------------------------------------------------------------------------- */
MaterialCohesive::MaterialCohesive(SolidMechanicsModel & model, const ID & id)
- : Material(model, id), facet_filter("facet_filter", id),
+ : Material(model, id, "SolidMechanicsFEEngine"),
+ facet_filter(
+ std::make_shared<ElementTypeMapArray<Idx>>("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),
+ reversible_energy(registerInternal<Real, CohesiveInternalField>(
+ "reversible_energy", 1)),
+ total_energy(
+ registerInternal<Real, CohesiveInternalField>("total_energy", 1)),
+ opening(registerInternal<Real, CohesiveInternalField>("opening",
+ spatial_dimension)),
+ tractions(registerInternal<Real, CohesiveInternalField>(
+ "tractions", spatial_dimension)),
+ contact_tractions(registerInternal<Real, CohesiveInternalField>(
+ "contact_tractions", spatial_dimension)),
+ contact_opening(registerInternal<Real, CohesiveInternalField>(
+ "contact_opening", spatial_dimension)),
+ delta_max(registerInternal<Real, CohesiveInternalField>("delta max", 1)),
use_previous_delta_max(false), use_previous_opening(false),
- damage("damage", *this), sigma_c("sigma_c", *this),
- normals("normal", *this) {
-
+ damage(registerInternal<Real, CohesiveInternalField>("damage", 1)),
+ sigma_c(registerInternal<Real, FacetRandomInternalField>("sigma_c", 1)),
+ model(&aka::as_type<SolidMechanicsModelCohesive>(model)),
+ normals(registerInternal<Real, CohesiveInternalField>(
+ "normal", spatial_dimension)) {
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);
-
- if (this->model->getIsExtrinsic()) {
- this->facet_filter.initialize(this->model->getMeshFacets(),
- _spatial_dimension = spatial_dimension - 1,
- _element_kind = _ek_regular);
- }
-
- 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);
+ this->getElementFilter().initialize(this->model->getMesh(),
+ _spatial_dimension = spatial_dimension,
+ _element_kind = _ek_cohesive);
if (this->model->getIsExtrinsic()) {
- this->sigma_c.initialize(1);
+ this->getFacetFilter().initialize(this->model->getMeshFacets(),
+ _spatial_dimension =
+ spatial_dimension - 1,
+ _element_kind = _ek_regular);
}
- 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();
- }
+
+ this->opening.initializeHistory();
+ this->tractions.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);
+ for (auto type : getElementFilter().elementTypes(spatial_dimension,
+ ghost_type, _ek_cohesive)) {
+ auto & elem_filter = getElementFilter(type, ghost_type);
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);
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 = 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 (Int el = 0; el < nb_element; ++el) {
auto current_quad = elem_filter(el) * nb_quadrature_points;
for (Int q = 0; q < nb_quadrature_points; ++q, ++traction_it,
++contact_traction_it, ++current_quad, ++traction_cpy_it) {
auto && shapes_filtered = shapes_filtered_begin[current_quad];
*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 = 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);
auto int_t_N = std::make_shared<Array<Real>>(
nb_element, 2 * spatial_dimension * size_of_shapes, "int_t_N");
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 (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;
}
/// assemble
model->getDOFManager().assembleElementalArrayLocalArray(
*int_t_N, internal_force, type, ghost_type, 1, elem_filter);
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void MaterialCohesive::assembleStiffnessMatrix(GhostType ghost_type) {
-
AKANTU_DEBUG_IN();
- for (auto type : element_filter.elementTypes(spatial_dimension, ghost_type,
- _ek_cohesive)) {
+ for (auto type : getElementFilter().elementTypes(spatial_dimension,
+ ghost_type, _ek_cohesive)) {
auto nb_quadrature_points =
fem_cohesive.getNbIntegrationPoints(type, ghost_type);
auto nb_nodes_per_element = Mesh::getNbNodesPerElement(type);
- const auto & shapes = fem_cohesive.getShapes(type, ghost_type);
- auto & elem_filter = element_filter(type, ghost_type);
+ auto & elem_filter = getElementFilter(type, ghost_type);
auto nb_element = elem_filter.size();
if (nb_element == 0U) {
continue;
}
+ const auto & shapes = fem_cohesive.getShapes(type, ghost_type);
auto size_of_shapes = shapes.getNbComponent();
auto shapes_filtered = std::make_shared<Array<Real>>(
nb_element * nb_quadrature_points, size_of_shapes, "filtered shapes");
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);
-
+ A.zero();
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 = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points,
spatial_dimension * spatial_dimension, "tangent_stiffness_matrix");
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, 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 = std::make_unique<Array<Real>>(
nb_element * nb_quadrature_points, size_at_nt_d_n_a, "A^t*N^t*D*N*A");
- Matrix<Real> N(spatial_dimension, spatial_dimension * nb_nodes_per_element);
+ Matrix<Real> N(spatial_dimension, spatial_dimension * size_of_shapes);
- for (auto && data :
+ for (auto && [At_Nt_D_N_A, D, shapes] :
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))) {
-
- 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 (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}}}
*{\partial{\delta}}
* \mathbf{P} d\Gamma \Delta \mathbf{U}} @f$
**/
- auto && NA = N * A;
+ Matrix<Real> NA = N * A;
At_Nt_D_N_A = (D * NA).transpose() * NA;
}
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);
model->getDOFManager().assembleElementalMatricesToMatrix(
"K", "displacement", *K_e, type, ghost_type, _unsymmetric, elem_filter);
}
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(
+ for (const auto & type : getElementFilter().elementTypes(
spatial_dimension, ghost_type, _ek_cohesive)) {
- auto & elem_filter = element_filter(type, ghost_type);
+ auto & elem_filter = getElementFilter(type, ghost_type);
auto nb_element = elem_filter.size();
if (nb_element == 0) {
continue;
}
/// compute normals @f$\mathbf{n}@f$
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(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();
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));
+ position, normal, ghost_type,
+ getElementFilter(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");
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));
+ getElementFilter(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(
+ for (const auto & type : getElementFilter().elementTypes(
spatial_dimension, _not_ghost, _ek_cohesive)) {
erev +=
fem_cohesive.integrate(reversible_energy(type, _not_ghost), type,
- _not_ghost, element_filter(type, _not_ghost));
+ _not_ghost, getElementFilter(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(
+ for (const auto & type : getElementFilter().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));
+ getElementFilter(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(
+ for (const auto & type : getElementFilter().elementTypes(
spatial_dimension, _not_ghost, _ek_cohesive)) {
- auto & el_filter = element_filter(type, _not_ghost);
+ auto & el_filter = getElementFilter(type, _not_ghost);
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 (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 9ee5a7f10..a7bc0bec2 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,242 +1,242 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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
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*/,
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(ElementType el_type,
- GhostType ghost_type = _not_ghost) = 0;
+ virtual void computeTraction(ElementType /*el_type*/,
+ GhostType /*ghost_type*/ = _not_ghost) {
+ AKANTU_TO_IMPLEMENT();
+ }
/// parallelism functions
- inline Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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, Idx);
- AKANTU_GET_MACRO_BY_ELEMENT_TYPE(FacetFilter, facet_filter, Idx);
- AKANTU_GET_MACRO_AUTO(FacetFilter, facet_filter);
+ 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_AUTO_NOT_CONST(FacetFilter, *facet_filter);
// AKANTU_GET_MACRO(ElementFilter, element_filter, const
// ElementTypeMapArray<UInt> &);
/// compute reversible energy
auto getReversibleEnergy() -> Real;
/// compute dissipated energy
auto getDissipatedEnergy() -> Real;
/// compute contact energy
auto getContactEnergy() -> Real;
/// get energy
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, const Element & element
// ) override {
// return Material::getEnergy(energy_id, element);
// }
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
protected:
/// list of facets assigned to this material
- ElementTypeMapArray<Idx> facet_filter;
+ std::shared_ptr<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;
+ CohesiveInternalField<Real> & reversible_energy;
/// total energy by quadrature point
- CohesiveInternalField<Real> total_energy;
+ CohesiveInternalField<Real> & total_energy;
protected:
/// opening in all elements and quadrature points
- CohesiveInternalField<Real> opening;
+ CohesiveInternalField<Real> & opening;
/// traction in all elements and quadrature points
- CohesiveInternalField<Real> tractions;
+ CohesiveInternalField<Real> & tractions;
/// traction due to contact
- CohesiveInternalField<Real> contact_tractions;
+ CohesiveInternalField<Real> & contact_tractions;
/// normal openings for contact tractions
- CohesiveInternalField<Real> contact_opening;
+ CohesiveInternalField<Real> & contact_opening;
/// maximum displacement
- CohesiveInternalField<Real> delta_max;
+ 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;
+ CohesiveInternalField<Real> & damage;
+
+ /// critical stress
+ FacetRandomInternalField<Real> & sigma_c;
/// pointer to the solid mechanics model for cohesive elements
SolidMechanicsModelCohesive * model;
- /// critical stress
- RandomInternalField<Real, FacetInternalField> sigma_c;
-
/// critical displacement
- Real delta_c;
+ Real delta_c{0.};
/// array to temporarily store the normals
- CohesiveInternalField<Real> normals;
+ CohesiveInternalField<Real> & normals;
};
} // namespace akantu
/* -------------------------------------------------------------------------- */
/* inline functions */
/* -------------------------------------------------------------------------- */
-#include "cohesive_internal_field_tmpl.hh"
+#include "cohesive_internal_field_tmpl.hh" // NOLINT(unused-includes)
#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_includes.hh b/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
deleted file mode 100644
index d13b14c76..000000000
--- a/src/model/solid_mechanics/solid_mechanics_model_cohesive/materials/material_cohesive_includes.hh
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * 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_CMAKE_LIST_MATERIALS
-// #include "material_cohesive.hh"
-// #include "material_cohesive_bilinear.hh"
-// #include "material_cohesive_exponential.hh"
-// #include "material_cohesive_linear.hh"
-// #include "material_cohesive_linear_fatigue.hh"
-// #include "material_cohesive_linear_friction.hh"
-// #include "material_cohesive_linear_uncoupled.hh"
-// #endif
-
-#define AKANTU_COHESIVE_MATERIAL_LIST \
- ((2, (cohesive_linear, MaterialCohesiveLinear)))( \
- (2, (cohesive_linear_fatigue, MaterialCohesiveLinearFatigue)))( \
- (2, (cohesive_linear_friction, MaterialCohesiveLinearFriction)))( \
- (2, (cohesive_linear_uncoupled, MaterialCohesiveLinearUncoupled)))( \
- (2, (cohesive_bilinear, MaterialCohesiveBilinear)))( \
- (2, (cohesive_exponential, MaterialCohesiveExponential)))
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 a8c782f89..1319eff0e 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,98 +1,96 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 Int MaterialCohesive::addFacet(const Element & element) {
- auto & f_filter = facet_filter(element.type, element.ghost_type);
+ auto & f_filter = getFacetFilter(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 Int MaterialCohesive::getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const {
+ const SynchronizationTag & tag) const {
switch (tag) {
case SynchronizationTag::_smm_stress: {
- return 2 * spatial_dimension * sizeof(Real) *
+ return 2 * spatial_dimension * Int(sizeof(Real)) *
this->getModel().getNbIntegrationPoints(elements,
"CohesiveFEEngine");
}
case SynchronizationTag::_smmc_damage: {
- return sizeof(Real) * this->getModel().getNbIntegrationPoints(
- elements, "CohesiveFEEngine");
+ return Int(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");
+ packInternalFieldHelper(tractions, buffer, elements);
+ packInternalFieldHelper(contact_tractions, buffer, elements);
break;
}
case SynchronizationTag::_smmc_damage:
- packElementDataHelper(damage, buffer, elements, "CohesiveFEEngine");
+ packInternalFieldHelper(damage, buffer, elements);
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");
+ unpackInternalFieldHelper(tractions, buffer, elements);
+ unpackInternalFieldHelper(contact_tractions, buffer, elements);
break;
}
case SynchronizationTag::_smmc_damage:
- unpackElementDataHelper(damage, buffer, elements, "CohesiveFEEngine");
+ unpackInternalFieldHelper(damage, buffer, elements);
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 9a8c3fbfa..0d0b90690 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,661 +1,627 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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.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;
+ for (auto && [old_node, new_node] : zip(old_nodes, new_nodes)) {
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, Int dim, const ID & id,
- std::shared_ptr<DOFManager> dof_manager)
+ const 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;
+ tmp_material_selector->setFallback(this->getConstitutiveLawSelector());
+ this->setConstitutiveLawSelector(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);
+ SynchronizationTag::_constitutive_law_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();
+ auto && [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() {
+void SolidMechanicsModelCohesive::initConstitutiveLaws() {
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");
- }
+ instantiateMaterials();
- material_selector->setFallback(cohesive_index);
+ auto & material_selector = this->getConstitutiveLawSelector();
// 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());
+ _default_value =
+ DefaultMaterialCohesiveSelector::getDefaultCohesiveMaterial(*this));
for_each_element(
mesh_facets,
[&](auto && element) {
- auto mat_index = (*material_selector)(element);
- auto & mat = aka::as_type<MaterialCohesive>(*materials[mat_index]);
+ auto mat_index = material_selector(element);
+ if (not mat_index) {
+ return;
+ }
+ auto & mat =
+ aka::as_type<MaterialCohesive>(this->getConstitutiveLaw(mat_index));
+
facet_material(element) = mat_index;
if (is_extrinsic) {
mat.addFacet(element);
}
},
_spatial_dimension = spatial_dimension - 1, _ghost_type = _not_ghost);
- SolidMechanicsModel::initMaterials();
+ SolidMechanicsModel::initConstitutiveLaws();
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);
+ auto 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;
}
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) {
+ this->for_each_constitutive_law([&](auto && material) {
if (aka::is_of_type<MaterialCohesive>(material)) {
- continue;
+ return;
}
/// initialize the interpolation function
- material->initElementalFieldInterpolation(elements_quad_facets);
- }
+ material.initElementalFieldInterpolation(elements_quad_facets);
+ });
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModelCohesive::assembleInternalForces() {
AKANTU_DEBUG_IN();
// f_int += f_int_cohe
- for (auto & material : this->materials) {
+ this->for_each_constitutive_law([&](auto && material) {
try {
- auto & mat = aka::as_type<MaterialCohesive>(*material);
+ 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);
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) {
+ this->for_each_constitutive_law([&](auto && material) {
if (not aka::is_of_type<MaterialCohesive>(material)) {
/// interpolate stress on facet quadrature points positions
- material->interpolateStressOnFacets(facet_stress, by_elem_result);
+ 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)) {
+ this->for_each_constitutive_law([&](auto && material) {
+ if (aka::is_of_type<MaterialCohesive>(material)) {
/// check which not ghost cohesive elements are to be created
- auto * mat_cohesive = aka::as_type<MaterialCohesive>(mat.get());
- mat_cohesive->checkInsertion();
+ auto & mat_cohesive = aka::as_type<MaterialCohesive>(material);
+ mat_cohesive.checkInsertion();
}
- }
+ });
/// insert cohesive elements
- UInt nb_new_elements = inserter->insertElements();
+ auto nb_new_elements = inserter->insertElements();
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<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) {
+ const auto * cohesive_event =
+ dynamic_cast<const CohesiveNewNodesEvent *>(&event);
+ if (cohesive_event == nullptr) {
return;
}
const auto & old_nodes = cohesive_event->getOldNodesList();
auto copy = [this, &new_nodes, &old_nodes](auto & arr) {
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"));
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);
+ this->for_each_constitutive_law([](auto && mat) {
+ 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;
+ stream << space << "]\n";
}
/* -------------------------------------------------------------------------- */
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();
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 3db77d68e..c4c96d4d9 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,298 +1,298 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, Int dim = _all_dimensions,
const ID & id = "solid_mechanics_model_cohesive",
- std::shared_ptr<DOFManager> dof_manager = nullptr);
-
- ~SolidMechanicsModelCohesive() override;
+ const std::shared_ptr<DOFManager> & dof_manager = nullptr);
/* ------------------------------------------------------------------------ */
/* 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;
+ void initConstitutiveLaws() 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<Idx> & nodes_list,
+ void onNodesAdded(const Array<Idx> & new_nodes,
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:
- Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override;
+ [[nodiscard]] 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:
- Int getNbQuadsForFacetCheck(const Array<Element> & elements) const;
+ [[nodiscard]] 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;
+ void packUnpackFacetStressDataHelper(
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element) const;
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// get facet 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, Idx);
/// get facet material
AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(FacetMaterial, facet_material, Idx);
/// get facet material
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<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 768f9229e..b4791234d 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,294 +1,295 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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" // NOLINT(unused-includes)
#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 (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 (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 (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 818376287..35b0dec68 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,481 +1,439 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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];
+ const auto & cohesive_element =
+ 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) {
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);
+ packUnpackFacetStressDataHelper<T, true>(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 {
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & elements) const {
bool element_rank = false;
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");
}
auto ghost_type = mesh_facets.getElementToSubelement()(el)[0].ghost_type;
- if (pack_helper) {
+ if constexpr (pack_helper) {
element_rank = ghost_type != _not_ghost;
} else {
element_rank = ghost_type == _not_ghost;
}
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) {
+ if constexpr (pack_helper) {
buffer << data;
} else {
buffer >> data;
}
}
}
}
/* -------------------------------------------------------------------------- */
Int SolidMechanicsModelCohesive::getNbQuadsForFacetCheck(
const Array<Element> & elements) const {
Int nb_quads = 0;
const auto & fe_engine = this->getFEEngine("FacetsFEEngine");
for (const auto & el : elements) {
auto nb_quad_per_facet =
fe_engine.getNbIntegrationPoints(el.type, el.ghost_type);
nb_quads += nb_quad_per_facet;
}
return nb_quads;
}
/* -------------------------------------------------------------------------- */
Int SolidMechanicsModelCohesive::getNbData(
const Array<Element> & elements, const SynchronizationTag & tag) const {
AKANTU_DEBUG_IN();
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: {
auto nb_quads = getNbQuadsForFacetCheck(elements);
size += nb_quads * spatial_dimension * spatial_dimension * sizeof(Real);
break;
}
- case SynchronizationTag::_material_id: {
+ case SynchronizationTag::_constitutive_law_id: {
for (auto && element : elements) {
if (Mesh::getSpatialDimension(element.type) ==
(spatial_dimension - 1)) {
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) {
+ } 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;
+ Int 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));
+ Int(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);
- });
+ if (tag != SynchronizationTag::_smmc_facets) {
+ size += CLHParent::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: {
+ case SynchronizationTag::_constitutive_law_id: {
for (auto && element : elements) {
if (Mesh::getSpatialDimension(element.type) !=
(spatial_dimension - 1)) {
continue;
}
- buffer << material_index(element);
+ buffer << this->getConstitutiveLawByElement()(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);
- });
+ if (tag != SynchronizationTag::_smmc_facets) {
+ CLHParent::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_stress: {
unpackFacetStressDataHelper(facet_stress, buffer, elements);
break;
}
- case SynchronizationTag::_material_id: {
+ case SynchronizationTag::_constitutive_law_id: {
for (auto && element : elements) {
if (Mesh::getSpatialDimension(element.type) !=
(spatial_dimension - 1)) {
continue;
}
Int recv_mat_index;
buffer >> recv_mat_index;
- auto & mat_index = material_index(element);
+ auto & mat_index = getConstitutiveLawByElement()(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]);
+ auto & mat =
+ aka::as_type<MaterialCohesive>(getConstitutiveLaw(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) {
- Int recv_mat_index;
- buffer >> recv_mat_index;
- 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 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);
- });
+ if (tag != SynchronizationTag::_smmc_facets) {
+ CLHParent::unpackData(buffer, elements, tag);
}
}
AKANTU_DEBUG_OUT();
}
/* -------------------------------------------------------------------------- */
} // namespace akantu
diff --git a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh b/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh
deleted file mode 100644
index 6729f9c07..000000000
--- a/src/model/solid_mechanics/solid_mechanics_model_inline_impl.hh
+++ /dev/null
@@ -1,103 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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"
-/* -------------------------------------------------------------------------- */
-
-#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) {
- 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 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 388de34e1..de840ca23 100644
--- a/src/model/solid_mechanics/solid_mechanics_model_io.cc
+++ b/src/model/solid_mechanics/solid_mechanics_model_io.cc
@@ -1,311 +1,218 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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<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<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, Int spatial_dimension, ElementKind kind) {
std::shared_ptr<dumpers::Field> field;
if (field_name == "partitions") {
field = mesh.createElementalField<Int, dumpers::ElementPartitionField>(
mesh.getConnectivities(), group_name, spatial_dimension, kind);
} else if (field_name == "material_index") {
field =
mesh.createElementalField<Idx, Vector<Idx>, dumpers::ElementalField>(
- material_index, group_name, spatial_dimension, kind);
+ getConstitutiveLawByElement(), 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, Int step) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(dumper_name, step);
}
/* -------------------------------------------------------------------------- */
void SolidMechanicsModel::dump(const std::string & dumper_name, Real time,
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(Int step) {
EventManager::sendEvent(SolidMechanicsModelEvent::BeforeDumpEvent());
this->onDump();
mesh.dump(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_material.cc b/src/model/solid_mechanics/solid_mechanics_model_material.cc
deleted file mode 100644
index 29ce1c214..000000000
--- a/src/model/solid_mechanics/solid_mechanics_model_material.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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");
-
- 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<Idx> * filter) {
-
- for_each_element(
- mesh,
- [&](auto && element) {
- auto mat_index = (*material_selector)(element);
- AKANTU_DEBUG_ASSERT(
- 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/solid_mechanics/solid_mechanics_model_tmpl.hh b/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh
deleted file mode 100644
index f30b35746..000000000
--- a/src/model/solid_mechanics/solid_mechanics_model_tmpl.hh
+++ /dev/null
@@ -1,50 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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.hh"
-/* -------------------------------------------------------------------------- */
-
-#ifndef AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH_
-#define AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH_
-
-namespace akantu {
-
-#define FWD(...) ::std::forward<decltype(__VA_ARGS__)>(__VA_ARGS__)
-
-/* -------------------------------------------------------------------------- */
-template <typename Operation>
-void SolidMechanicsModel::splitByMaterial(const Array<Element> & elements,
- Operation && op) const {
- std::vector<Array<Element>> elements_per_mat(materials.size());
- this->splitElementByMaterial(elements, elements_per_mat);
-
- for (auto && mat : zip(materials, elements_per_mat)) {
- FWD(op)(FWD(*std::get<0>(mat)), FWD(std::get<1>(mat)));
- }
-}
-
-#undef FWD
-/* -------------------------------------------------------------------------- */
-
-} // namespace akantu
-
-#endif /* AKANTU_SOLID_MECHANICS_MODEL_TMPL_HH_ */
diff --git a/src/model/structural_mechanics/structural_mechanics_model.hh b/src/model/structural_mechanics/structural_mechanics_model.hh
index 06b99b420..e3ddbb459 100644
--- a/src/model/structural_mechanics/structural_mechanics_model.hh
+++ b/src/model/structural_mechanics/structural_mechanics_model.hh
@@ -1,380 +1,381 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "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, 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,
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.
+ * \param name the name associated to this 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
+ * \param material_index The index of requested 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
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_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/solver/solver_vector.hh b/src/solver/solver_vector.hh
index 053b2ad8b..4c34f4c0c 100644
--- a/src/solver/solver_vector.hh
+++ b/src/solver/solver_vector.hh
@@ -1,85 +1,85 @@
/**
* Copyright (©) 2013-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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;
+ virtual SolverVector & copy(const SolverVector & y) = 0;
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;
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_default.hh b/src/solver/solver_vector_default.hh
index ea4f94164..3d4ceb90d 100644
--- a/src/solver/solver_vector_default.hh
+++ b/src/solver/solver_vector_default.hh
@@ -1,145 +1,145 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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.hh"
/* -------------------------------------------------------------------------- */
#include <utility>
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_VECTOR_DEFAULT_HH_
#define AKANTU_SOLVER_VECTOR_DEFAULT_HH_
namespace akantu {
class DOFManagerDefault;
} // namespace akantu
namespace akantu {
class SolverVectorArray : public SolverVector {
public:
SolverVectorArray(DOFManagerDefault & dof_manager, const ID & id);
SolverVectorArray(const SolverVectorArray & vector, const ID & id);
~SolverVectorArray() override = default;
virtual Array<Real> & getVector() = 0;
virtual const Array<Real> & getVector() const = 0;
void printself(std::ostream & stream, int indent = 0) const override {
std::string space(indent, AKANTU_INDENT);
stream << space << "SolverVectorArray [" << std::endl;
stream << space << " + id: " << id << std::endl;
this->getVector().printself(stream, indent + 1);
stream << space << "]" << std::endl;
}
using SolverVector::isDistributed;
};
/* -------------------------------------------------------------------------- */
template <class Array_> class SolverVectorArrayTmpl : public SolverVectorArray {
public:
SolverVectorArrayTmpl(DOFManagerDefault & dof_manager, Array_ & vector,
const ID & id = "solver_vector_default")
: SolverVectorArray(dof_manager, id), dof_manager(dof_manager),
vector(vector) {}
template <class A = Array_,
std::enable_if_t<not std::is_reference<A>::value> * = nullptr>
SolverVectorArrayTmpl(DOFManagerDefault & dof_manager,
const ID & id = "solver_vector_default")
: SolverVectorArray(dof_manager, id), dof_manager(dof_manager),
vector(0, 1, id + ":vector") {}
SolverVectorArrayTmpl(const SolverVectorArrayTmpl & vector,
const ID & id = "solver_vector_default")
: SolverVectorArray(vector, id), dof_manager(vector.dof_manager),
vector(vector.vector) {}
operator const Array<Real> &() const override { return getVector(); };
virtual operator Array<Real> &() { return getVector(); };
SolverVector & operator+(const SolverVector & y) override;
- SolverVector & operator=(const SolverVector & y) override;
+ SolverVector & copy(const SolverVector & y) override;
void resize() override {
static_assert(not std::is_const<std::remove_reference_t<Array_>>::value,
"Cannot resize a const Array");
this->vector.resize(this->localSize(), 0.);
++this->release_;
}
void set(Real val) override {
static_assert(not std::is_const<std::remove_reference_t<Array_>>::value,
"Cannot clear a const Array");
this->vector.set(val);
++this->release_;
}
virtual
bool
isDistributed()
const
override
{ return false; }
public:
Array<Real> & getVector() override { return vector; }
const Array<Real> & getVector() const override { return vector; }
Int size() const override;
Int localSize() const override;
virtual Array<Real> & getGlobalVector() { return this->vector; }
virtual void setGlobalVector(const Array<Real> & solution) {
this->vector.copy(solution);
}
bool isFinite() const override { return vector.isFinite(); }
protected:
DOFManagerDefault & dof_manager;
Array_ vector;
template <class A> friend class SolverVectorArrayTmpl;
};
/* -------------------------------------------------------------------------- */
using SolverVectorDefault = SolverVectorArrayTmpl<Array<Real>>;
/* -------------------------------------------------------------------------- */
template <class Array>
using SolverVectorDefaultWrap = SolverVectorArrayTmpl<Array &>;
template <class Array>
decltype(auto) make_solver_vector_default_wrap(DOFManagerDefault & dof_manager,
Array & vector) {
return SolverVectorDefaultWrap<Array>(dof_manager, vector);
}
} // namespace akantu
/* -------------------------------------------------------------------------- */
#include "solver_vector_default_tmpl.hh"
/* -------------------------------------------------------------------------- */
#endif /* AKANTU_SOLVER_VECTOR_DEFAULT_HH_ */
diff --git a/src/solver/solver_vector_default_tmpl.hh b/src/solver/solver_vector_default_tmpl.hh
index 849122ea7..4ddbf0a2e 100644
--- a/src/solver/solver_vector_default_tmpl.hh
+++ b/src/solver/solver_vector_default_tmpl.hh
@@ -1,76 +1,76 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_vector_default.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_SOLVER_VECTOR_DEFAULT_TMPL_HH_
#define AKANTU_SOLVER_VECTOR_DEFAULT_TMPL_HH_
namespace akantu {
/* -------------------------------------------------------------------------- */
inline SolverVectorArray::SolverVectorArray(DOFManagerDefault & dof_manager,
const ID & id)
: SolverVector(dof_manager, id) {}
/* -------------------------------------------------------------------------- */
inline SolverVectorArray::SolverVectorArray(const SolverVectorArray & vector,
const ID & id)
: SolverVector(vector, id) {}
/* -------------------------------------------------------------------------- */
template <class Array_>
SolverVector &
SolverVectorArrayTmpl<Array_>::operator+(const SolverVector & y) {
const auto & y_ = aka::as_type<SolverVectorArray>(y);
this->vector += y_.getVector();
++this->release_;
return *this;
}
/* -------------------------------------------------------------------------- */
template <class Array_>
SolverVector &
-SolverVectorArrayTmpl<Array_>::operator=(const SolverVector & y) {
+SolverVectorArrayTmpl<Array_>::copy(const SolverVector & y) {
const auto & y_ = aka::as_type<SolverVectorArray>(y);
this->vector.copy(y_.getVector());
this->release_ = y.release();
return *this;
}
/* -------------------------------------------------------------------------- */
template <class Array_> inline Int SolverVectorArrayTmpl<Array_>::size() const {
return this->dof_manager.getSystemSize();
}
/* -------------------------------------------------------------------------- */
template <class Array_>
inline Int SolverVectorArrayTmpl<Array_>::localSize() const {
return dof_manager.getLocalSystemSize();
}
} // namespace akantu
#endif /* AKANTU_SOLVER_VECTOR_DEFAULT_TMPL_HH_ */
diff --git a/src/solver/solver_vector_petsc.cc b/src/solver/solver_vector_petsc.cc
index a6c52ecf6..619ca7414 100644
--- a/src/solver/solver_vector_petsc.cc
+++ b/src/solver/solver_vector_petsc.cc
@@ -1,288 +1,288 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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.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.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.data();
Array<Real> scaled_array;
if (scale_factor != 1.) {
scaled_array.copy(values, false);
scaled_array *= scale_factor;
to_add = scaled_array.data();
}
PETSc_call(VecSetOption, x, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
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.data();
Array<Real> scaled_array;
if (scale_factor != 1.) {
scaled_array.copy(values, false);
scaled_array *= scale_factor;
to_add = scaled_array.data();
}
PETSc_call(VecSetOption, x, VEC_IGNORE_NEGATIVE_INDICES, PETSC_TRUE);
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.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) {
+SolverVector & SolverVectorPETSc::copy(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 33689dead..7e6140906 100644
--- a/src/solver/solver_vector_petsc.hh
+++ b/src/solver/solver_vector_petsc.hh
@@ -1,200 +1,200 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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;
+ SolverVector & copy(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;
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.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_solver_eigen.cc b/src/solver/sparse_solver_eigen.cc
new file mode 100644
index 000000000..5d7860856
--- /dev/null
+++ b/src/solver/sparse_solver_eigen.cc
@@ -0,0 +1,73 @@
+#include "sparse_solver_eigen.hh"
+#include "dof_manager_default.hh"
+#include "solver_vector_default.hh"
+#include "sparse_matrix_aij.hh"
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+SparseSolverEigen::SparseSolverEigen(DOFManagerDefault & dof_manager,
+ const ID & matrix_id, const ID & id)
+ : SparseSolver(dof_manager, matrix_id, id), dof_manager(dof_manager) {
+ AKANTU_DEBUG_ASSERT(communicator.getNbProc() == 1,
+ "This solver does not work in parallel");
+}
+
+/* -------------------------------------------------------------------------- */
+void SparseSolverEigen::setA() {
+ const auto & Aij =
+ aka::as_type<SparseMatrixAIJ>(dof_manager.getMatrix(matrix_id));
+
+ if (this->last_value_release == Aij.getRelease() and
+ this->last_value_release != -1) {
+ return;
+ }
+
+ using Triplet = Eigen::Triplet<Real>;
+ std::vector<Triplet> triplets;
+ triplets.reserve(Aij.getNbNonZero());
+ for (auto && [i, j, a] : zip(Aij.getIRN(), Aij.getJCN(), Aij.getA())) {
+ triplets.emplace_back(i - 1, j - 1, a);
+ if (Aij.getMatrixType() == _symmetric and i != j) {
+ triplets.emplace_back(j - 1, i - 1, a);
+ }
+ }
+
+ A.resize(Aij.size(), Aij.size());
+ A.setZero();
+ A.setFromTriplets(triplets.begin(), triplets.end());
+}
+
+/* -------------------------------------------------------------------------- */
+void SparseSolverEigen::solve() {
+ const auto & Aij =
+ aka::as_type<SparseMatrixAIJ>(dof_manager.getMatrix(matrix_id));
+
+ auto & b_ = aka::as_type<SolverVectorDefault>(this->dof_manager.getResidual())
+ .getGlobalVector();
+ Array<Real> x_(b_.size() * b_.getNbComponent());
+
+ VectorProxy<Real> x(x_.data(), x_.size() * x_.getNbComponent());
+ VectorProxy<Real> b(b_.data(), b_.size() * b_.getNbComponent());
+
+ setA();
+
+ if (this->last_profile_release != Aij.getProfileRelease()) {
+ solver.analyzePattern(A);
+ this->last_profile_release = Aij.getProfileRelease();
+ }
+
+ if (this->last_value_release != Aij.getValueRelease()) {
+ solver.factorize(A);
+ this->last_value_release = Aij.getValueRelease();
+ }
+
+ x = solver.solve(b);
+
+ aka::as_type<SolverVectorDefault>(this->dof_manager.getSolution())
+ .setGlobalVector(x_);
+
+ this->dof_manager.splitSolutionPerDOFs();
+}
+
+} // namespace akantu
diff --git a/src/model/common/non_linear_solver/non_linear_solver_linear.hh b/src/solver/sparse_solver_eigen.hh
similarity index 67%
copy from src/model/common/non_linear_solver/non_linear_solver_linear.hh
copy to src/solver/sparse_solver_eigen.hh
index 1d97b83ba..702030064 100644
--- a/src/model/common/non_linear_solver/non_linear_solver_linear.hh
+++ b/src/solver/sparse_solver_eigen.hh
@@ -1,67 +1,76 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "sparse_solver_mumps.hh"
+#include "sparse_solver.hh"
+/* -------------------------------------------------------------------------- */
+#include <Eigen/Sparse>
+#include <Eigen/SparseLU>
/* -------------------------------------------------------------------------- */
-#ifndef AKANTU_NON_LINEAR_SOLVER_LINEAR_HH_
-#define AKANTU_NON_LINEAR_SOLVER_LINEAR_HH_
+#ifndef AKANTU_SOLVER_EIGEN_HH_
+#define AKANTU_SOLVER_EIGEN_HH_
namespace akantu {
class DOFManagerDefault;
-}
+} // namespace akantu
namespace akantu {
-class NonLinearSolverLinear : public NonLinearSolver {
+class SparseSolverEigen : public SparseSolver {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public:
- NonLinearSolverLinear(DOFManagerDefault & dof_manager,
- const NonLinearSolverType & non_linear_solver_type,
- const ID & id = "non_linear_solver_linear");
- ~NonLinearSolverLinear() override;
+ SparseSolverEigen(DOFManagerDefault & dof_manager, const ID & matrix_id,
+ const ID & id = "sparse_solver_eigen");
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
- /// Function that solve the non linear system described by the dof manager and
- /// the solver callback functions
- void solve(SolverCallback & solver_callback) override;
+ void initialize() override{};
+
+ /// solve using residual and solution from the dof_manager
+ void solve() override;
+
+private:
+ void setA();
- AKANTU_GET_MACRO_NOT_CONST(Solver, solver, SparseSolverMumps &);
- AKANTU_GET_MACRO(Solver, solver, const SparseSolverMumps &);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
-protected:
+private:
+ /// DOFManager used by the Eigen implementation of the SparseSolver
DOFManagerDefault & dof_manager;
- /// Sparse solver used for the linear solves
- SparseSolverMumps solver;
+ /// matrix release at last solve
+ Int last_profile_release{-1};
+
+ /// matrix release at last solve
+ Int last_value_release{-1};
+
+ Eigen::SparseMatrix<Real> A;
+ Eigen::SparseLU<Eigen::SparseMatrix<Real>> solver;
};
} // namespace akantu
-#endif /* AKANTU_NON_LINEAR_SOLVER_LINEAR_HH_ */
+#endif /* AKANTU_SOLVER_EIGEN_HH_ */
diff --git a/src/synchronizer/communication_buffer.hh b/src/synchronizer/communication_buffer.hh
index dbbd1f8b5..640b62556 100644
--- a/src/synchronizer/communication_buffer.hh
+++ b/src/synchronizer/communication_buffer.hh
@@ -1,187 +1,188 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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(std::size_t size)
- : buffer(size, 1, char()) {
+ // NOLINTNEXTLINE(cppcoreguidelines-narrowing-conversions)
+ CommunicationBufferTemplated(std::size_t size = 0) : 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 &
+ operator=(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(std::size_t size);
/// resize the internal buffer allocate always
inline void reserve(std::size_t size);
/// clear buffer context
inline void zero();
private:
inline void packResize(std::size_t size);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
- [[deprecated("use data instead to be stl compatible")]] inline char *
+ [[deprecated("use data instead to be stl compatible"),
+ nodiscard]] inline char *
storage() {
return buffer.data();
};
- [[deprecated("use data instead to be stl compatible")]] inline const char *
+ [[deprecated("use data instead to be stl compatible"),
+ nodiscard]] inline const char *
storage() const {
return buffer.data();
};
[[nodiscard]] inline char * data() { return buffer.data(); };
[[nodiscard]] inline const char * data() const { return buffer.data(); };
/* ------------------------------------------------------------------------ */
/* Operators */
/* ------------------------------------------------------------------------ */
public:
/// printing tool
template <typename T>
inline std::string extractStream(std::size_t block_size);
/// packing data
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, 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, 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, std::enable_if_t<aka::is_tensor_v<T>> * = nullptr>
- inline CommunicationBufferTemplated & operator>>(T & to_pack);
+ inline CommunicationBufferTemplated & operator>>(T & to_unpack);
template <typename T>
inline CommunicationBufferTemplated & operator>>(std::vector<T> & to_unpack);
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, 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 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
[[nodiscard]] inline std::size_t getPackedSize() const {
return ptr_pack - buffer.data();
};
/// return the size in bytes of data left to be unpacked
[[nodiscard]] inline std::size_t getLeftToUnpack() const {
return buffer.size() - (ptr_unpack - buffer.data());
};
/// return the global size allocated
[[nodiscard]] inline std::size_t size() const { return buffer.size(); };
/// is the buffer empty
[[nodiscard]] inline bool empty() const {
return (getPackedSize() == 0) and (getLeftToUnpack() == 0);
}
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private:
/// current position for packing
- char * ptr_pack;
+ char * ptr_pack{nullptr};
/// current position for unpacking
- char * ptr_unpack;
+ char * ptr_unpack{nullptr};
/// 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 cd9056d29..6fcc532c0 100644
--- a/src/synchronizer/communication_buffer_inline_impl.hh
+++ b/src/synchronizer/communication_buffer_inline_impl.hh
@@ -1,288 +1,295 @@
/**
* Copyright (©) 2011-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
+
+// NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic,
+// cppcoreguidelines-pro-type-reinterpret-cast,
+// cppcoreguidelines-narrowing-conversions)
/* -------------------------------------------------------------------------- */
template <bool is_static>
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 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 std::size_t CommunicationBufferTemplated<is_static>::sizeInBuffer(
const std::vector<T> & data) {
std::size_t size = data.size() * sizeof(T) + sizeof(size_t);
return size;
}
template <bool is_static>
inline std::size_t CommunicationBufferTemplated<is_static>::sizeInBuffer(
const std::string & data) {
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(std::size_t size) {
if (not is_static) {
char * values = buffer.data();
auto nb_packed = ptr_pack - values;
if (std::size_t(buffer.size()) > nb_packed + size) {
return;
}
buffer.resize(nb_packed + size);
ptr_pack = buffer.data() + nb_packed;
ptr_unpack = buffer.data() + (ptr_unpack - values);
}
}
/* -------------------------------------------------------------------------- */
template <bool is_static>
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) {
std::size_t size = sizeInBuffer(to_pack);
packResize(size);
AKANTU_DEBUG_ASSERT(
(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, 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) {
std::size_t size = sizeInBuffer(to_unpack);
alignas(alignof(T)) std::array<char, sizeof(T)> aligned_ptr;
- memcpy(aligned_ptr.data(), ptr_unpack, size);
+ std::memcpy(aligned_ptr.data(), ptr_unpack, size);
auto * tmp = reinterpret_cast<T *>(aligned_ptr.data());
AKANTU_DEBUG_ASSERT(
(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;
}
/* -------------------------------------------------------------------------- */
template <bool is_static>
template <typename Tensor, std::enable_if_t<aka::is_tensor_v<Tensor>> *>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator<<(const Tensor & to_pack) {
std::size_t size = sizeInBuffer(to_pack);
packResize(size);
AKANTU_DEBUG_ASSERT(
(buffer.data() + buffer.size()) >= (ptr_pack + size),
"Packing too much data in the CommunicationBufferTemplated");
- memcpy(ptr_pack, to_pack.data(), size);
+ std::memcpy(ptr_pack, to_pack.data(), size);
ptr_pack += size;
return *this;
}
/* --------------------------------------------------------------------------
*/
template <bool is_static>
template <typename Tensor, std::enable_if_t<aka::is_tensor_v<Tensor>> *>
inline CommunicationBufferTemplated<is_static> &
CommunicationBufferTemplated<is_static>::operator>>(Tensor & to_unpack) {
std::size_t size = sizeInBuffer(to_unpack);
AKANTU_DEBUG_ASSERT(
(buffer.data() + buffer.size()) >= (ptr_unpack + size),
"Unpacking too much data in the CommunicationBufferTemplated");
- memcpy(to_unpack.data(), ptr_unpack, size);
+ std::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<<(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) {
- std::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(std::size_t block_size) {
std::stringstream str;
auto * ptr = reinterpret_cast<T *>(buffer.data());
auto sz = buffer.size() / sizeof(T);
auto sz_block = block_size / sizeof(T);
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 << " ";
+ str << "\n" << n_block << " ";
++n_block;
}
str << *ptr << " ";
++ptr;
}
return str.str();
}
/* --------------------------------------------------------------------------
*/
template <bool is_static>
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(std::size_t size) {
char * values = buffer.data();
std::size_t nb_packed = ptr_pack - values;
buffer.resize(size);
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.data();
ptr_unpack = buffer.data();
}
+// NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic,
+// cppcoreguidelines-pro-type-reinterpret-cast,
+// cppcoreguidelines-narrowing-conversions)
} // namespace akantu
diff --git a/src/synchronizer/data_accessor.cc b/src/synchronizer/data_accessor.cc
deleted file mode 100644
index 0a1ef75df..000000000
--- a/src/synchronizer/data_accessor.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
- * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
- *
- * This file is part of Akantu
- *
- * Akantu is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You 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) {
- Int nb_component = data.getNbComponent();
- auto data_it = make_view(data, nb_component).begin();
-
- for (const auto & el : elements) {
- 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) {
- for (const auto & el : element) {
- 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);
-
- if (pack_helper) {
- buffer << data;
- } else {
- buffer >> data;
- }
- }
-}
-
-/* -------------------------------------------------------------------------- */
-template <typename T, bool pack_helper>
-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<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(Idx);
-DECLARE_HELPERS(bool);
-/* -------------------------------------------------------------------------- */
-
-} // namespace akantu
diff --git a/src/synchronizer/data_accessor.hh b/src/synchronizer/data_accessor.hh
index bfaead9b2..8e487a0b5 100644
--- a/src/synchronizer/data_accessor.hh
+++ b/src/synchronizer/data_accessor.hh
@@ -1,350 +1,379 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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;
+
+ DataAccessorBase(const DataAccessorBase & other) = default;
+ DataAccessorBase(DataAccessorBase && other) = default;
+
+ DataAccessorBase & operator=(const DataAccessorBase & other) = default;
+ DataAccessorBase & operator=(DataAccessorBase && other) = 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 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;
[[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*/){};
+private:
+ template <
+ typename T, bool pack_helper, class Func,
+ std::enable_if_t<not std::is_base_of_v<FEEngine, std::decay_t<Func>>> * =
+ nullptr>
+ static void packUnpackElementalDataHelper(
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element,
+ Func && data_per_element);
+
/* ------------------------------------------------------------------------ */
public:
template <typename T, bool pack_helper>
- static void
- packUnpackNodalDataHelper(Array<T> & data, CommunicationBuffer & buffer,
- const Array<Element> & elements, const Mesh & mesh);
+ static void packUnpackNodalDataHelper(
+ std::conditional_t<pack_helper, const Array<T>, 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,
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element);
+
+ /* ------------------------------------------------------------------------ */
+ template <typename T, bool pack_helper>
+ static void packUnpackElementalDataHelper(
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element,
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);
+ packUnpackNodalDataHelper<T, true>(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);
+ const Array<Element> & elements) {
+ packUnpackElementalDataHelper<T, true>(data_to_pack, buffer, elements);
}
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) {
+ const Array<Element> & elements) {
+ packUnpackElementalDataHelper<T, false>(data_to_unpack, buffer, elements);
+ }
+ /* ------------------------------------------------------------------------ */
+ template <typename T>
+ static inline void packElementalDataHelper(
+ const ElementTypeMapArray<T> & data_to_pack, CommunicationBuffer & buffer,
+ const Array<Element> & elements, const FEEngine & fem) {
+ packUnpackElementalDataHelper<T, true>(data_to_pack, buffer, elements, fem);
+ }
+
+ template <typename T>
+ static inline void unpackElementalDataHelper(
+ ElementTypeMapArray<T> & data_to_unpack, CommunicationBuffer & buffer,
+ const Array<Element> & elements, const FEEngine & fem) {
packUnpackElementalDataHelper<T, false>(data_to_unpack, buffer, elements,
- per_quadrature_point, fem);
+ fem);
}
};
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
template <> class DataAccessor<Idx> : public virtual DataAccessorBase {
public:
DataAccessor() = default;
- ~DataAccessor() override = default;
[[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<Idx> & dofs);
+ static void packUnpackDOFDataHelper(
+ std::conditional_t<pack_helper, const Array<T>, Array<T>> & data,
+ CommunicationBuffer & buffer, const Array<Idx> & dofs);
template <typename T>
static inline void packDOFDataHelper(const Array<T> & data_to_pack,
CommunicationBuffer & buffer,
const Array<Idx> & dofs) {
- packUnpackDOFDataHelper<T, true>(const_cast<Array<T> &>(data_to_pack),
- buffer, dofs);
+ packUnpackDOFDataHelper<T, true>(data_to_pack, buffer, dofs);
}
template <typename T>
static inline void unpackDOFDataHelper(Array<T> & data_to_unpack,
CommunicationBuffer & buffer,
const Array<Idx> & dofs) {
packUnpackDOFDataHelper<T, false>(data_to_unpack, buffer, dofs);
}
};
/* -------------------------------------------------------------------------- */
template <typename T> class AddOperation {
public:
inline T operator()(const T & a, const T & b) { return a + b; };
};
template <typename T> class IdentityOperation {
public:
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:
/* ------------------------------------------------------------------------ */
- Int getNbData(const Array<Entity> & entities,
- const SynchronizationTag & tag) const override {
+ [[nodiscard]] 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 << 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());
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 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:
/* ------------------------------------------------------------------------ */
- Int getNbData(const Array<Element> & elements,
- const SynchronizationTag & tag) const override {
+ [[nodiscard]] 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
+#include "data_accessor_tmpl.hh"
+
#endif /* AKANTU_DATA_ACCESSOR_HH_ */
diff --git a/src/synchronizer/data_accessor_tmpl.hh b/src/synchronizer/data_accessor_tmpl.hh
new file mode 100644
index 000000000..5421f4ed4
--- /dev/null
+++ b/src/synchronizer/data_accessor_tmpl.hh
@@ -0,0 +1,115 @@
+/**
+ * Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
+ * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
+ *
+ * This file is part of Akantu
+ *
+ * Akantu is free software: you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You 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"
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_DATA_ACCESSOR_TMPL_HH
+#define AKANTU_DATA_ACCESSOR_TMPL_HH
+
+namespace akantu {
+
+/* -------------------------------------------------------------------------- */
+template <typename T, bool pack_helper>
+void DataAccessor<Element>::packUnpackNodalDataHelper(
+ std::conditional_t<pack_helper, const Array<T>, Array<T>> & data,
+ CommunicationBuffer & buffer, const Array<Element> & elements,
+ const Mesh & mesh) {
+ Int nb_component = data.getNbComponent();
+ auto data_it = make_view(data, nb_component).begin();
+
+ for (const auto & el : elements) {
+ auto && conn = mesh.getConnectivity(el);
+
+ for (auto node : conn) {
+ auto && data_vect = data_it[node];
+ if constexpr (pack_helper) {
+ buffer << data_vect;
+ } else {
+ buffer >> data_vect;
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+template <
+ typename T, bool pack_helper, class Func,
+ std::enable_if_t<not std::is_base_of_v<FEEngine, std::decay_t<Func>>> *>
+void DataAccessor<Element>::packUnpackElementalDataHelper(
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element,
+ Func && data_per_element) {
+ for (const auto & el : element) {
+ auto nb_component = data_to_pack(el.type, el.ghost_type).getNbComponent();
+ auto nb_data_per_elem = data_per_element(el) * nb_component;
+ auto && data = data_to_pack.get(el, nb_data_per_elem);
+
+ if constexpr (pack_helper) {
+ buffer << data;
+ } else {
+ buffer >> data;
+ }
+ }
+}
+/* ------------------------------------------------------------------------ */
+template <typename T, bool pack_helper>
+void DataAccessor<Element>::packUnpackElementalDataHelper(
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element) {
+ packUnpackElementalDataHelper<T, pack_helper>(
+ data_to_pack, buffer, element, [](auto && /*el*/) { return 1; });
+}
+
+/* ------------------------------------------------------------------------ */
+template <typename T, bool pack_helper>
+void DataAccessor<Element>::packUnpackElementalDataHelper(
+ std::conditional_t<pack_helper, const ElementTypeMapArray<T>,
+ ElementTypeMapArray<T>> & data_to_pack,
+ CommunicationBuffer & buffer, const Array<Element> & element,
+ const FEEngine & fem) {
+ packUnpackElementalDataHelper<T, pack_helper>(
+ data_to_pack, buffer, element, [&fem](auto && el) {
+ return fem.getNbIntegrationPoints(el.type, el.ghost_type);
+ });
+}
+
+/* -------------------------------------------------------------------------- */
+template <typename T, bool pack_helper>
+void DataAccessor<Idx>::packUnpackDOFDataHelper(
+ std::conditional_t<pack_helper, const Array<T>, Array<T>> & data,
+ CommunicationBuffer & buffer, const Array<Idx> & dofs) {
+ auto data_ptr = make_view(data).begin();
+ for (const auto & dof : dofs) {
+ if constexpr (pack_helper) {
+ buffer << data_ptr[dof];
+ } else {
+ buffer >> data_ptr[dof];
+ }
+ }
+}
+
+} // namespace akantu
+
+#endif /* AKANTU_DATA_ACCESSOR_TMPL_HH */
diff --git a/test/ci/debian:testing/Dockerfile b/test/ci/debian:testing/Dockerfile
new file mode 100644
index 000000000..eaa82fd6c
--- /dev/null
+++ b/test/ci/debian:testing/Dockerfile
@@ -0,0 +1,14 @@
+FROM debian:testing-slim
+
+# for release generations
+RUN apt -qq update && apt -qq -y install \
+ cargo curl git \
+ && rm -rf /var/lib/apt/lists/*
+
+RUN cargo install markdown-extract \
+ && mv ~/.cargo/bin/markdown-extract /usr/bin \
+ && rm -rf ~/.cargo
+
+RUN curl -fSsL -o /usr/bin/release-cli \
+ https://gitlab.com/gitlab-org/release-cli/-/releases/v0.16.0/downloads/bin/release-cli-linux-amd64 \
+ && chmod +x /usr/bin/release-cli
diff --git a/test/ci/macosx/build_env.sh b/test/ci/macosx/build_env.sh
new file mode 100644
index 000000000..6d82ebac3
--- /dev/null
+++ b/test/ci/macosx/build_env.sh
@@ -0,0 +1,5 @@
+export SPACK_DISABLE_LOCAL_CONFIG=true
+export SPACK_USER_CACHE_PATH=".spack-cache"
+
+source spack/share/spack/setup-env.sh
+spack env activate macosx
diff --git a/test/ci/macosx/configure_env.sh b/test/ci/macosx/configure_env.sh
new file mode 100644
index 000000000..3e97b3f0a
--- /dev/null
+++ b/test/ci/macosx/configure_env.sh
@@ -0,0 +1,12 @@
+export SPACK_DISABLE_LOCAL_CONFIG=true
+export SPACK_USER_CACHE_PATH=".spack-cache"
+
+# spack environment
+git clone -b v0.20.2 https://github.com/spack/spack
+source spack/share/spack/setup-env.sh
+
+mkdir spack/var/spack/environments
+cp -r ./test/ci/macosx spack/var/spack/environments
+
+spack env activate macosx
+spack install
diff --git a/test/ci/macosx/make-wheels.sh b/test/ci/macosx/make-wheels.sh
new file mode 100755
index 000000000..8ff04a063
--- /dev/null
+++ b/test/ci/macosx/make-wheels.sh
@@ -0,0 +1,15 @@
+#!/usr/bin/env bash
+set -eo pipefail
+
+set +x
+
+source spack/share/spack/setup-env.sh
+spack env activate macosx
+
+python3 -m venv venv
+source venv/bin/activate
+
+pip3 install -r dev-requirements.txt
+
+pip3 wheel . --no-deps -w dist/
+delocate-wheel -w wheelhouse_macos/ -v dist/*.whl
diff --git a/test/ci/macosx/spack.yaml b/test/ci/macosx/spack.yaml
new file mode 100644
index 000000000..f9d64f5f1
--- /dev/null
+++ b/test/ci/macosx/spack.yaml
@@ -0,0 +1,34 @@
+spack:
+ view: true
+ concretizer:
+ unify: true
+ compilers:
+ - compiler:
+ spec: apple-clang@=15.0.0
+ paths:
+ cc: /usr/bin/clang
+ cxx: /usr/bin/clang++
+ f77: null
+ fc: null
+ flags: {}
+ operating_system: macos
+ target: aarch64
+ modules: []
+ environment: {}
+ extra_rpaths: []
+ specs:
+ - cmake ~ncurses
+ - 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
+ - eigen
+ packages:
+ openssl:
+ externals:
+ - spec: openssl@3.1.3
+ prefix: /opt/homebrew
+ gmake:
+ externals:
+ - spec: gmake@3.81
+ prefix: /usr
diff --git a/test/ci/manylinux:2014_x86_64/Dockerfile b/test/ci/manylinux:2014_x86_64/Dockerfile
index 1ed6ccdc1..948cd539f 100644
--- a/test/ci/manylinux:2014_x86_64/Dockerfile
+++ b/test/ci/manylinux:2014_x86_64/Dockerfile
@@ -1,75 +1,75 @@
FROM quay.io/pypa/manylinux2014_x86_64 as builder
ENV LANG en_US.UTF-8
-RUN yum install -y xz zlib-devel openssl-devel
+RUN yum install -y xz openssl-devel perl-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://github.com/spack/spack.git -b v0.20.2
-RUN cd /softs && git clone https://gitlab.com/epfl-lsms/spack-packages.git
+#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
+#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 CROSS_ROOT /opt/rh/devtoolset-10/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/build_env.sh b/test/ci/manylinux:2014_x86_64/build_env.sh
new file mode 100644
index 000000000..e3dafb1d8
--- /dev/null
+++ b/test/ci/manylinux:2014_x86_64/build_env.sh
@@ -0,0 +1 @@
+export CMAKE_PREFIX_PATH=/softs/view
diff --git a/test/ci/manylinux:2014_x86_64/configure_env.sh b/test/ci/manylinux:2014_x86_64/configure_env.sh
new file mode 100644
index 000000000..e3dafb1d8
--- /dev/null
+++ b/test/ci/manylinux:2014_x86_64/configure_env.sh
@@ -0,0 +1 @@
+export CMAKE_PREFIX_PATH=/softs/view
diff --git a/test/ci/make-wheels.sh b/test/ci/manylinux:2014_x86_64/make-wheels.sh
similarity index 100%
rename from test/ci/make-wheels.sh
rename to test/ci/manylinux:2014_x86_64/make-wheels.sh
diff --git a/test/ci/manylinux:2014_x86_64/spack.yaml b/test/ci/manylinux:2014_x86_64/spack.yaml
index d4df5a262..64ef4b32a 100644
--- a/test/ci/manylinux:2014_x86_64/spack.yaml
+++ b/test/ci/manylinux:2014_x86_64/spack.yaml
@@ -1,34 +1,50 @@
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
+ - openblas +pic threads=none
- eigen
- mumps ~mpi ~complex ~float
view: /softs/view
concretizer:
unify: true
+
+ packages:
+ cmake:
+ externals:
+ - spec: cmake@3.27.7
+ prefix: /usr/local
+ gmake:
+ externals:
+ - spec: gmake@3.82
+ prefix: /usr
+ openssl:
+ externals:
+ - spec: openssl@1.0.2k-fips
+ prefix: /usr
+ perl:
+ externals:
+ - spec: perl@5.16.3
+ prefix: /usr
diff --git a/test/test_common/test_voigt_helper.cc b/test/test_common/test_voigt_helper.cc
index 7de8330a4..d6babe8b0 100644
--- a/test/test_common/test_voigt_helper.cc
+++ b/test/test_common/test_voigt_helper.cc
@@ -1,153 +1,153 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 Int dim = Dim_v::value;
VoigtHelperFixture() {
switch (this->dim) {
case 1: {
- indices.push_back({0, 0});
+ indices.emplace_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});
+ indices.emplace_back(0, 0);
+ indices.emplace_back(1, 1);
+ indices.emplace_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});
+ indices.emplace_back(0, 0);
+ indices.emplace_back(1, 1);
+ indices.emplace_back(2, 2);
+ indices.emplace_back(1, 2);
+ indices.emplace_back(0, 2);
+ indices.emplace_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 <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 (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 (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 (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 (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 (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_model/patch_tests/data/heat_transfer_input.dat b/test/test_model/patch_tests/data/heat_transfer_input.dat
index 6c031caec..a5565620d 100644
--- a/test/test_model/patch_tests/data/heat_transfer_input.dat
+++ b/test/test_model/patch_tests/data/heat_transfer_input.dat
@@ -1,7 +1,10 @@
model heat_transfer_model [
+ constitutive_law heat_diffusion [
+ name = dummy
density = 8940
capacity = 385
conductivity = [[401, 0, 0],\
[0, 401, 0],\
- [0, 0, 401]]
+ [0, 0, 401]]
+ ]
]
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 cfeb4365e..f17b309e6 100644
--- a/test/test_model/patch_tests/patch_test_linear_fixture.hh
+++ b/test/test_model/patch_tests/patch_test_linear_fixture.hh
@@ -1,172 +1,173 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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
+// #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 Int dim = ElementClass<type>::getSpatialDimension();
- virtual void SetUp() {
+ void SetUp() override {
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() {
+ void TearDown() override {
model.reset(nullptr);
mesh.reset(nullptr);
}
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)
+ if (method != _static) {
this->model->setTimeStep(0.8 * this->model->getStableTimeStep());
+ }
}
virtual void applyBC() {
auto & boundary = this->model->getBlockedDOFs();
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(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) {
Matrix<Real> gradient(dof.getNbComponent(), dim);
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) {
auto pgrad = prescribed_gradient(dofs);
for (auto & grad :
make_view(gradient, gradient.getNbComponent() / dim, dim)) {
auto diff = grad - pgrad;
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) {
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 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 (Int i = 0; i < dof.size(); ++i) {
dof(i) = this->alpha(i, 0);
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();
Vector<Real> ref_dof(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;
+ for (auto && [X, u] : zip(make_view(coordinates, dim),
+ make_view(dofs, dofs.getNbComponent()))) {
+ setLinearDOF(ref_dof, X);
+ auto diff = u - ref_dof;
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 type_, typename M>
+// constexpr ElementType TestPatchTestLinear<type_, M>::type;
-template <typename tuple_, typename M>
-constexpr Int TestPatchTestLinear<tuple_, M>::dim;
+// template <typename tuple_, typename M>
+// 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_fixture.hh b/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.hh
index f42460afc..d88d371bd 100644
--- a/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.hh
+++ b/test/test_model/patch_tests/patch_test_linear_heat_transfer_fixture.hh
@@ -1,67 +1,73 @@
/**
* Copyright (©) 2018-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "patch_test_linear_fixture.hh"
/* -------------------------------------------------------------------------- */
#ifndef AKANTU_PATCH_TEST_LINEAR_HEAT_TRANSFER_FIXTURE_HH_
#define AKANTU_PATCH_TEST_LINEAR_HEAT_TRANSFER_FIXTURE_HH_
/* -------------------------------------------------------------------------- */
template <typename type>
class TestPatchTestHTMLinear
: public TestPatchTestLinear<type, HeatTransferModel> {
using parent = TestPatchTestLinear<type, HeatTransferModel>;
public:
void applyBC() override {
parent::applyBC();
auto & temperature = this->model->getTemperature();
this->applyBConDOFs(temperature);
}
void initModel(const AnalysisMethod & method,
const std::string & material_file) override {
TestPatchTestLinear<type, HeatTransferModel>::initModel(method,
material_file);
- if (method != _static)
+ if (method != _static) {
this->model->setTimeStep(0.5 * this->model->getStableTimeStep());
+ }
}
void checkAll() {
auto & temperature = this->model->getTemperature();
- Matrix<Real> C = this->model->get("conductivity");
+ auto && cl = this->model->getConstitutiveLaw(0);
+ Matrix<Real> C = cl.get("conductivity");
this->checkDOFs(temperature);
- this->checkGradient(this->model->getTemperatureGradient(this->type),
- temperature);
+
+ auto && grad_T = cl.template getArray<Real>("∇u", this->type);
+ this->checkGradient(grad_T, temperature);
+
+ auto && K_grad_T = cl.template getArray<Real>("D∇u", this->type);
+
this->checkResults(
[&](const Matrix<Real> & grad_T) { return C * grad_T.transpose(); },
- this->model->getKgradT(this->type), temperature);
+ K_grad_T, temperature);
}
};
using htm_types = gtest_list_t<TestElementTypes>;
TYPED_TEST_SUITE(TestPatchTestHTMLinear, htm_types, );
#endif /* AKANTU_PATCH_TEST_LINEAR_HEAT_TRANSFER_FIXTURE_HH_ */
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 0d0a8de70..ba5c69aaa 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,52 +1,57 @@
#!/usr/bin/env python3
__copyright__ = (
"Copyright (©) 2018-2023 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")
+ cl = self.model.getConstitutiveLaw(0)
+ C = cl.getMatrix("conductivity")
+
self.checkDOFs(temperature)
- self.checkGradient(self.model.getTemperatureGradient(self.elem_type),
+
+ grad_t = cl.getInternalReal("∇u")
+ self.checkGradient(grad_t(self.elem_type),
temperature)
self.prescribed_gradient(temperature)
+ flux = cl.getInternalReal("D∇u")
self.checkResults(lambda grad_T: C.dot(grad_T.T),
- self.model.getKgradT(self.elem_type),
+ flux(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/test_patch_linear_heat_transfer_explicit.py b/test/test_model/patch_tests/test_patch_linear_heat_transfer_explicit.py
old mode 100644
new mode 100755
diff --git a/test/test_model/patch_tests/test_patch_linear_heat_transfer_implicit.py b/test/test_model/patch_tests/test_patch_linear_heat_transfer_implicit.py
old mode 100644
new mode 100755
diff --git a/test/test_model/patch_tests/test_patch_linear_heat_transfer_static.py b/test/test_model/patch_tests/test_patch_linear_heat_transfer_static.py
old mode 100644
new mode 100755
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 794700b3f..4fffacfe6 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,116 +1,116 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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, 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<Idx> &, const NewNodesEvent &) override {}
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<Idx> &,
const RemovedElementsEvent &) override {}
void onElementsChanged(const Array<Element> &, const Array<Element> &,
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");
for (const auto & type : quadrature_points_coordinates.elementTypes(
spatial_dimension, ghost_type)) {
q.type = type;
auto & quads = quadrature_points_coordinates(type, ghost_type);
this->getFEEngine().computeIntegrationPointsCoordinates(quads, type,
ghost_type);
auto quad_it = quads.cbegin(quads.getNbComponent());
auto quad_end = quads.cend(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 computeNonLocalContribution(GhostType) override {}
void updateLocalInternal(ElementTypeMapReal &, GhostType,
ElementKind) override {}
void updateNonLocalInternal(ElementTypeMapReal &, GhostType,
ElementKind) override {}
const auto & getNonLocalManager() const { return manager; }
private:
NonLocalManager manager;
};
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 d5bd0462f..86ba39ba2 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,51 +1,48 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
TestMaterial<dim>::TestMaterial(SolidMechanicsModel & model, const ID & id)
- : Parent(model, id), grad_u_nl("grad_u non local", *this) {
+ : Parent(model, id),
+ grad_u_nl(this->registerInternal("grad_u non local", dim * dim)) {
this->is_non_local = true;
- this->grad_u_nl.initialize(dim * dim);
}
/* -------------------------------------------------------------------------- */
template <Int dim> void TestMaterial<dim>::registerNonLocalVariables() {
- this->model.getNonLocalManager().registerNonLocalVariable(
+ this->getModel().getNonLocalManager().registerNonLocalVariable(
this->gradu.getName(), grad_u_nl.getName(), dim * dim);
- this->model.getNonLocalManager()
+ this->getModel()
+ .getNonLocalManager()
.getNeighborhood(this->getNeighborhoodName())
.registerNonLocalVariable(grad_u_nl.getName());
}
/* -------------------------------------------------------------------------- */
// Instantiate the material for the 3 dimensions
-template class TestMaterial<1>;
-template class TestMaterial<2>;
-template class TestMaterial<3>;
-
-static bool material_is_allocated_test_material =
+const bool material_is_allocated_test_material [[maybe_unused]] =
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 b9054239a..97031596b 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,62 +1,62 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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;
+ 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 bab1c85ac..a19ad9de4 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,53 +1,50 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <Int dim>
TestMaterialDamage<dim>::TestMaterialDamage(SolidMechanicsModel & model,
const ID & id)
- : Parent(model, id), grad_u_nl("grad_u non local", *this) {
+ : Parent(model, id),
+ grad_u_nl(this->registerInternal("grad_u non local", dim * dim)) {
this->is_non_local = true;
- this->grad_u_nl.initialize(dim * dim);
}
/* -------------------------------------------------------------------------- */
template <Int dim> void TestMaterialDamage<dim>::registerNonLocalVariables() {
- this->model.getNonLocalManager().registerNonLocalVariable(
+ this->getModel().getNonLocalManager().registerNonLocalVariable(
this->gradu.getName(), grad_u_nl.getName(), dim * dim);
- this->model.getNonLocalManager()
+ this->getModel()
+ .getNonLocalManager()
.getNeighborhood(this->getNeighborhoodName())
.registerNonLocalVariable(grad_u_nl.getName());
}
/* -------------------------------------------------------------------------- */
// Instantiate the material for the 3 dimensions
-template class TestMaterialDamage<1>;
-template class TestMaterialDamage<2>;
-template class TestMaterialDamage<3>;
-
-static bool material_is_allocated_test_material =
+const bool material_is_allocated_test_material [[maybe_unused]] =
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 4716394fd..fcd1bf422 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,63 +1,61 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 registerNonLocalVariables() final;
- void computeNonLocalStress(ElementType, GhostType) override final{};
+ void computeNonLocalStress(ElementType /*element_type*/,
+ GhostType /*ghost_type*/) final{};
void insertQuadsInNeighborhoods(GhostType ghost_type);
-protected:
- // ID getNeighborhoodName() override { return "test_region"; }
-
/* ------------------------------------------------------------------------ */
/* Members */
/* ------------------------------------------------------------------------ */
private:
- InternalField<Real> grad_u_nl;
+ InternalField<Real> & grad_u_nl;
};
#endif /* TEST_MATERIAL_DAMAGE_HH_ */
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 2d4be0521..661b212d3 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,175 +1,175 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "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 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 =
2. * Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
/// apply different strain in element 3 and 15
Matrix<Real> modified_strain =
Matrix<Real>::Identity(spatial_dimension, spatial_dimension);
/// apply constant grad_u field in all elements
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);
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 (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)) {
- std::cout << current_line << std::endl;
+ std::cout << current_line << "\n";
}
weights.close();
}
/// apply damage to not have the elements with lower strain impact the
/// averaging
for (Int m = 0; m < model.getNbMaterials(); ++m) {
auto & mat =
dynamic_cast<MaterialDamage<spatial_dimension> &>(model.getMaterial(m));
auto & damage = mat.getInternal<Real>("damage")(element_type, ghost_type);
auto dam_it = damage.begin();
auto dam_end = damage.end();
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) {
*dam_it = 0.9;
}
}
}
/// compute the non-local strains
model.assembleInternalForces();
neighborhood_1.saveWeights("after_0");
neighborhood_2.saveWeights("after_1");
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)) {
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);
Matrix<Real> difference_in_damaged_elements(spatial_dimension,
spatial_dimension);
for (Int m = 0; m < model.getNbMaterials(); ++m) {
difference_in_damaged_elements.zero();
auto & mat = model.getMaterial(m);
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) {
difference_in_damaged_elements += (*grad_u_nl_it);
} else {
difference = (*grad_u_nl_it) - applied_strain;
}
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();
}
if (test_result > 10.e-5) {
std::cout << "the total norm is: " << test_result << std::endl;
return EXIT_FAILURE;
}
}
diff --git a/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh b/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh
index 45280addf..ec2b4ef0c 100644
--- a/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh
+++ b/test/test_model/test_contact_mechanics_model/test_detector/test_detection_fixture.hh
@@ -1,201 +1,201 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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_mdoel.hh"
#include "solid_mechanics_model.hh"
#include "test_gtest_utils.hh"
/* -------------------------------------------------------------------------- */
#include <gtest/gtest.h>
#include <vector>
/* -------------------------------------------------------------------------- */
-#ifndef __AKANTU_TEST_DETECTION_FIXTURE_HH__
-#define __AKANTU_TEST_DETECTION_FIXTURE_HH__
+#ifndef AKANTU_TEST_DETECTION_FIXTURE_HH_
+#define AKANTU_TEST_DETECTION_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 TestCMMDFixture : public ::testing::Test {
public:
static constexpr ElementType type_1 = std::tuple_element_t<1, param_>::value;
static constexpr ElementType type_2 = std::tuple_element_t<2, param_>::value;
void Setup() override {
mesh = std::make_unique<Mesh>(this->dim);
if (Communicator::getStaticCommunicator().whoAmI() == 0) {
ASSERT_NO_THROW({ mesh->read(this->mesh_name); });
}
mesh->distribute();
}
void TearDown() override {
solid.reset(nullptr);
contact.reset(nullptr);
mesh.reset(nullptr);
}
void createModel() {
solid = std::make_unique<SolidmechanicsModel>(*mesh);
solid->initFull(_analysis_method = this->analysis_method);
contact = std::make_unique<ContactMechanicsModel>(*mesh);
contact->initFull(_analysis_method = this->detection_type);
auto && surface_selector = std::make_shared<PhysicalSurfaceSelector>(*mesh);
contact->getContactDetector().setSurfaceSelector(surface_selector);
}
void setInitialCondition(const Matrix<Real> & strain) {
for (auto && data :
zip(make_view(this->mesh->getNodes(), this->dim),
make_view(this->solid->getDisplacement(), this->dim))) {
const auto & pos = std::get<0>(data);
auto & disp = std::get<1>(data);
disp = strain * pos;
}
}
void steps(const Matrix<Real> & strain) {
StrainIncrement functor((1. / 300) * strain, this->dim == 1 ? _x : _y);
for (auto _ [[gnu::unused]] : arange(nb_steps)) {
this->solid->applyBC(functor, "loading");
this->solid->applyBC(functor, "fixed");
this->solid->solveStep();
}
}
void testImplicit() {
this->createModel();
auto & mat_el = this->solid->getMaterial("body");
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");
Real E = mat_el.get("E");
Real nu = mat_el.get("nu");
Matrix<Real> strain;
if (dim == 1) {
strain = {{1.}};
} else if (dim == 2) {
strain = {{-nu, 0.}, {0., 1. - nu}};
strain *= (1. + nu);
} else if (dim == 3) {
strain = {{-nu, 0., 0.}, {0., 1., 0.}, {0., 0., -nu}};
}
this->setInitialCondition((1 - 1e-5) * strain);
this->steps(1e-2 * strain);
this->contact->search();
}
void testExplicit() {
this->createModel();
auto & mat_el = this->solid->getMaterial("body");
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");
Real E = mat_el.get("E");
Real nu = mat_el.get("nu");
Matrix<Real> strain;
if (dim == 1) {
strain = {{-1.}};
} else if (dim == 2) {
strain = {{-nu, 0.}, {0., 1. - nu}};
strain *= (1. + nu);
} else if (dim == 3) {
strain = {{-nu, 0., 0.}, {0., 1., 0.}, {0., 0., -nu}};
}
this->setInitialCondition((1 - 1e-5) * strain);
this->steps(1e-2 * strain);
this->contact->search();
}
bool checkGap() {}
bool checkNormal() {}
bool checkCovariantBasis() {}
protected:
std::unique_ptr<Mesh> mesh;
std::unique_ptr<SolidMechanicsModel> solid;
std::unique_ptr<ContactMechanicsModel> contact;
std::string mesh_name{
std::to_string(detection_type) + std::to_string(type_1) +
(type_1 == type_2 ? "" : std::to_string(type_2)) + ".msh"};
AnalysisMethod analysis_method;
DetectionType detection_type;
};
/* -------------------------------------------------------------------------- */
using element_types = gtest_list_t<std::tuple<
std::tuple<_element_type_segment_2, _element_type_segement_2>,
std::tuple<_element_type_triangle_3, _element_type_triangle_3>,
std::tuple<_element_type_triangle_3, _element_type_quadrangle_4>,
std::tuple<_element_type_quadrangle_4, _element_type_quadrange_4>,
std::tuple<_element_type_tetrahedron_6, _element_type_tetrahedron_6>>>;
TYPED_TEST_SUITE(TestCMMDFixture, detection_types)
#endif
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 f374adda1..c35052c4a 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,156 +1,157 @@
/**
* Copyright (©) 2020-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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)
+ 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 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 (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 e16741b9e..26fcfc563 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,168 +1,169 @@
/**
* Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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)
+ for (T value = start; value <= stop; value += step) {
values.push_back(value);
+ }
return values;
}
int main(int argc, char * argv[]) {
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 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 (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_phase_field_model/CMakeLists.txt b/test/test_model/test_phase_field_model/CMakeLists.txt
index 794a7ab89..d0ce95afd 100644
--- a/test/test_model/test_phase_field_model/CMakeLists.txt
+++ b/test/test_model/test_phase_field_model/CMakeLists.txt
@@ -1,82 +1,82 @@
#===============================================================================
# Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
# Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
#
# This file is part of Akantu
#
# Akantu is free software: you can redistribute it and/or modify it under the
# terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with Akantu. If not, see <http://www.gnu.org/licenses/>.
#
#===============================================================================
register_test(test_phasefield_selector
SOURCES test_phasefield_selector.cc
FILES_TO_COPY phasefield_selector.dat phasefield_selector.msh
PACKAGE phase_field
)
register_test(test_phase_solid_coupling
SOURCES test_phase_solid_coupling.cc
FILES_TO_COPY material_coupling.dat test_one_element.msh
PACKAGE phase_field
)
register_test(test_phase_field_anisotropic
SOURCES test_phase_field_anisotropic.cc
FILES_TO_COPY material_hybrid.dat test_one_element.msh material_penalization.dat
PACKAGE phase_field
)
register_test(test_phase_field_deviatoric_split
SOURCES test_phase_field_deviatoric_split.cc
FILES_TO_COPY material_deviatoric.dat test_one_element.msh
PACKAGE phase_field
)
register_test(test_phase_field_optimal
SOURCES test_phase_field_optimal.cc
FILES_TO_COPY material_optimal.dat test_optimal_damage.msh
PACKAGE phase_field
)
register_test(test_phase_field_optimal_linear
SOURCES test_phase_field_optimal_linear.cc
FILES_TO_COPY material_optimal_linear.dat test_optimal_damage.msh
PACKAGE phase_field
)
register_test(test_phase_solid_explicit
SOURCES test_phase_solid_explicit.cc
FILES_TO_COPY material_coupling.dat test_one_element.msh
PACKAGE phase_field
)
register_test(test_multi_material
SOURCES test_multi_material.cc
FILES_TO_COPY material_multiple.dat test_two_element.msh
PACKAGE phase_field
UNSTABLE
)
register_test(test_penalization
SOURCES test_penalization.cc
- FILES_TO_COPY material_penalization.dat test_one_element.msh
+ FILES_TO_COPY material_penalization.dat test_four_elements.msh
PACKAGE phase_field
)
register_test(test_phase_field_linear
SOURCES test_phase_field_linear.cc
FILES_TO_COPY material_linear.dat test_one_element.msh
PACKAGE phase_field
)
diff --git a/test/test_model/test_phase_field_model/data.csv b/test/test_model/test_phase_field_model/data.csv
index b0fe48d16..2bd17e627 100644
--- a/test/test_model/test_phase_field_model/data.csv
+++ b/test/test_model/test_phase_field_model/data.csv
@@ -1 +1,2 @@
#strain stress damage analytical_sigma analytical_damage
+0 0 0 0 0 -nan -nan
diff --git a/test/test_model/test_phase_field_model/material_coupling.dat b/test/test_model/test_phase_field_model/material_coupling.dat
index 8ea425b7b..f2d806ef4 100644
--- a/test/test_model/test_phase_field_model/material_coupling.dat
+++ b/test/test_model/test_phase_field_model/material_coupling.dat
@@ -1,22 +1,22 @@
model solid_mechanics_model [
- material phasefield [
+ material phasefield [
name = plate
rho = 1.
E = 210.0
nu = 0.3
Plane_Stress = false
is_hybrid = false
]
]
model phase_field_model [
phasefield exponential [
name = plate
E = 210.0
nu = 0.3
gc = 5e-3
l0 = 0.3
Plane_Stress = false
isotropic = true
]
]
diff --git a/test/test_model/test_phase_field_model/test_penalization.cc b/test/test_model/test_phase_field_model/test_penalization.cc
index b32caed06..8b42555b6 100644
--- a/test/test_model/test_phase_field_model/test_penalization.cc
+++ b/test/test_model/test_phase_field_model/test_penalization.cc
@@ -1,188 +1,187 @@
#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_penalization.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("test_four_elements.msh");
CouplerSolidPhaseField coupler(mesh);
auto & model = coupler.getSolidMechanicsModel();
auto & phase = coupler.getPhaseFieldModel();
model.initFull(_analysis_method = _static);
auto & solver = model.getNonLinearSolver("static");
solver.set("max_iterations", 1000);
solver.set("threshold", 1e-8);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
auto & solver_phase = phase.getNonLinearSolver("static");
solver_phase.set("max_iterations", 1000);
solver_phase.set("threshold", 1e-8);
solver_phase.set("convergence_type", SolveConvergenceCriteria::_residual);
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 new_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 lambda = nu * E / ((1. + nu) * (1. - 2. * nu));
const Real mu = E / (2. + 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_energy{0.};
Real strain_energy_plus{0.};
Real strain_energy_minus{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 > 0) {
strain_energy_plus = axial_strain * axial_strain * (0.5 * lambda + mu);
strain_energy_minus = 0.;
} else {
strain_energy_plus = 0.5 * axial_strain * axial_strain * mu;
strain_energy_minus = axial_strain * axial_strain * 0.5 * (lambda + mu);
}
// if (strain_energy_plus > max_strain_energy) {
// max_strain_energy = strain_energy_plus;
// }
max_strain_energy = strain_energy_plus;
coupler.solve("static", "static");
phase.savePreviousState();
- phase.savePreviousDamage();
new_damage = 2. * (l0 / gc) * max_strain_energy /
(2. * (l0 / gc) * max_strain_energy + 1.);
if (new_damage > analytical_damage) {
analytical_damage = new_damage;
}
if (axial_strain < 0.) {
analytical_sigma = (1. - analytical_damage) * (1. - analytical_damage) *
axial_strain * mu +
axial_strain * (lambda + mu);
} else {
analytical_sigma = (lambda + 2. * mu) * axial_strain *
(1. - analytical_damage) * (1. - analytical_damage);
}
error_stress =
std::abs(analytical_sigma - stress(0, 3)) / std::abs(analytical_sigma);
error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage;
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
<< " " << error_damage << std::endl;
// if ((error_damage > 1e-8 or error_stress > 1e-8) and
// std::abs(axial_strain) > 1e-13) {
// std::cerr << std::left << std::setw(15) << "Step: " << s << std::endl;
// std::cerr << std::left << std::setw(15)
// << "Axial strain: " << axial_strain << std::endl;
// std::cerr << std::left << std::setw(15)
// << "An. damage: " << analytical_damage << std::endl;
// std::cerr << std::left << std::setw(15)
// << "Damage: " << damage(0) << std::endl;
// 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;
// }
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 (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 if (positions(n, 1) == 0.5) {
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 f2992cb55..4ddf2468e 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,185 +1,172 @@
/**
* Copyright (©) 2021-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "coupler_solid_phasefield.hh"
/* -------------------------------------------------------------------------- */
-#include <cmath>
#include <fstream>
-#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
const UInt spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
-void applyDisplacement(SolidMechanicsModel &, Real &);
+void applyDisplacement(SolidMechanicsModel & /*model*/, Real & /*disp*/);
/* -------------------------------------------------------------------------- */
int main(int argc, char * argv[]) {
std::ofstream os("data.csv");
- os << "#strain stress damage analytical_sigma analytical_damage" << std::endl;
+ os << "#strain stress damage analytical_sigma analytical_damage"
+ << "\n";
initialize("material_penalization.dat", argc, argv);
Mesh mesh(spatial_dimension);
mesh.read("test_one_element.msh");
CouplerSolidPhaseField coupler(mesh);
- auto & model = coupler.getSolidMechanicsModel();
- auto & phase = coupler.getPhaseFieldModel();
+ SolidMechanicsModel & model = coupler.getSolidMechanicsModel();
+ PhaseFieldModel & phase = coupler.getPhaseFieldModel();
model.initFull(_analysis_method = _static);
- auto & solver = model.getNonLinearSolver("static");
+ auto & solver = model.getNonLinearSolver();
solver.set("max_iterations", 1000);
solver.set("threshold", 1e-6);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
- auto & solver_phase = phase.getNonLinearSolver("static");
+ auto & solver_phase = phase.getNonLinearSolver();
solver_phase.set("max_iterations", 1000);
solver_phase.set("threshold", 1e-6);
solver_phase.set("convergence_type", SolveConvergenceCriteria::_residual);
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;
+ axial_strain = (1500. - 2. * s) * increment;
} else {
- axial_strain = (3 * double(s) - 3500) * increment;
+ axial_strain = (3. * s - 3500.) * increment;
}
applyDisplacement(model, axial_strain);
if (axial_strain > max_strain) {
max_strain = axial_strain;
}
coupler.solve("static", "static");
- phase.savePreviousDamage();
phase.savePreviousState();
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)) / std::abs(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) << "Step: " << s << std::endl;
- // std::cerr << std::left << std::setw(15)
- // << "Axial strain: " << axial_strain << std::endl;
- // std::cerr << std::left << std::setw(15)
- // << "An. damage: " << analytical_damage << std::endl;
- // std::cerr << std::left << std::setw(15)
- // << "Damage: " << damage(0) << std::endl;
- // 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;
- // }
+ 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 << "\n";
+ std::cerr << std::left << std::setw(15)
+ << "Error stress: " << error_stress << "\n";
+ return EXIT_FAILURE;
+ }
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
- << " " << error_damage << std::endl;
+ << " " << error_damage << "\n";
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 (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_field_deviatoric_split.cc b/test/test_model/test_phase_field_model/test_phase_field_deviatoric_split.cc
index d7010695e..dc7acfef4 100644
--- a/test/test_model/test_phase_field_model/test_phase_field_deviatoric_split.cc
+++ b/test/test_model/test_phase_field_model/test_phase_field_deviatoric_split.cc
@@ -1,185 +1,186 @@
#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_deviatoric.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 & solver = model.getNonLinearSolver("static");
solver.set("max_iterations", 1000);
solver.set("threshold", 1e-6);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", phase);
phase.setPhaseFieldSelector(selector);
phase.initFull(_analysis_method = _static);
auto & solver_phase = phase.getNonLinearSolver("static");
solver_phase.set("max_iterations", 1000);
solver_phase.set("threshold", 1e-6);
solver_phase.set("convergence_type", SolveConvergenceCriteria::_residual);
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 new_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 lambda = nu * E / ((1. + nu) * (1. - 2. * nu));
const Real mu = E / (2. + 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_energy{0.};
Real strain_energy_plus{0.};
Real strain_energy_minus{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 > 0) {
strain_energy_plus = axial_strain * axial_strain * (0.5 * lambda + mu);
strain_energy_minus = 0.;
} else {
- strain_energy_plus = 0.5 * axial_strain * axial_strain * mu;
- strain_energy_minus = axial_strain * axial_strain * 0.5 * (lambda + mu);
+ strain_energy_plus = 2. * axial_strain * axial_strain * mu / 3.;
+ strain_energy_minus =
+ axial_strain * axial_strain * (0.5 * lambda + mu / 3.);
}
- // if (strain_energy_plus > max_strain_energy) {
- // max_strain_energy = strain_energy_plus;
- // }
- max_strain_energy = strain_energy_plus;
+ if (strain_energy_plus > max_strain_energy) {
+ max_strain_energy = strain_energy_plus;
+ }
+ // max_strain_energy = strain_energy_plus;
coupler.solve("static", "static");
phase.savePreviousState();
- phase.savePreviousDamage();
new_damage = 2. * (l0 / gc) * max_strain_energy /
(2. * (l0 / gc) * max_strain_energy + 1.);
if (new_damage > analytical_damage) {
analytical_damage = new_damage;
}
+
if (axial_strain < 0.) {
analytical_sigma = (1. - analytical_damage) * (1. - analytical_damage) *
- axial_strain * mu +
- axial_strain * (lambda + mu);
+ axial_strain * 4. * mu / 3. +
+ axial_strain * (lambda + 2. * mu / 3.);
} else {
- analytical_sigma = (lambda + 2. * mu) * axial_strain *
+ analytical_sigma = (lambda + 6. * mu / 3.) * axial_strain *
(1. - analytical_damage) * (1. - analytical_damage);
}
error_stress =
std::abs(analytical_sigma - stress(0, 3)) / std::abs(analytical_sigma);
error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage;
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
<< " " << error_damage << std::endl;
if ((error_damage > 1e-8 or error_stress > 1e-8) and
std::abs(axial_strain) > 1e-13) {
std::cerr << std::left << std::setw(15) << "Step: " << s << std::endl;
std::cerr << std::left << std::setw(15)
<< "Axial strain: " << axial_strain << std::endl;
std::cerr << std::left << std::setw(15)
<< "An. damage: " << analytical_damage << std::endl;
std::cerr << std::left << std::setw(15) << "Damage: " << damage(0)
<< std::endl;
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;
}
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 (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 32338ab45..ca671b536 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,286 +1,286 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "material_phasefield_anisotropic.hh"
#include "non_linear_solver.hh"
#include "phase_field_model.hh"
#include "solid_mechanics_model.hh"
/* -------------------------------------------------------------------------- */
#include <fstream>
#include <iostream>
/* -------------------------------------------------------------------------- */
using namespace akantu;
const Int spatial_dimension = 2;
/* -------------------------------------------------------------------------- */
void applyDisplacement(SolidMechanicsModel &, Real &);
void computeStrainOnQuadPoints(SolidMechanicsModel &, PhaseFieldModel &,
GhostType);
void computeDamageOnQuadPoints(SolidMechanicsModel &, PhaseFieldModel &,
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 error_stress "
"error_damage error_energy"
<< 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);
auto & solver = model.getNonLinearSolver("static");
solver.set("max_iterations", 100);
solver.set("threshold", 1e-9);
solver.set("convergence_type", SolveConvergenceCriteria::_residual);
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.addDumpField("strain");
model.addDumpFieldVector("displacement");
model.addDumpField("damage");
model.dump();
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.};
Real analytical_energy{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 error_energy{0.};
for (Int s = 0; s < nbSteps; ++s) {
Real axial_strain = increment * s;
applyDisplacement(model, axial_strain);
model.solveStep("static");
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);
analytical_energy = analytical_damage * analytical_damage * 0.5 * gc / l0;
error_stress = std::abs(analytical_sigma - stress(0, 3)) / analytical_sigma;
error_damage = std::abs(analytical_damage - damage(0)) / analytical_damage;
error_energy =
std::abs(analytical_energy - phase.getEnergy()) / analytical_energy;
os << axial_strain << " " << stress(0, 3) << " " << damage(0) << " "
<< analytical_sigma << " " << analytical_damage << " " << error_stress
<< " " << error_damage << " " << error_energy << std::endl;
if (error_damage > 1e-8 or error_stress > 1e-8) {
std::cerr << std::left << std::setw(15) << "Step: " << s << std::endl;
std::cerr << std::left << std::setw(15)
<< "Axial strain: " << axial_strain << std::endl;
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;
std::cerr << std::left << std::setw(15)
<< "Error energy: " << error_energy << std::endl;
return EXIT_FAILURE;
}
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 (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, GhostType ghost_type) {
auto & mesh = solid.getMesh();
- auto nb_materials = solid.getNbMaterials();
- auto nb_phasefields = phase.getNbPhaseFields();
+ auto nb_materials = solid.getNbConstitutiveLaws();
+ auto nb_phasefields = phase.getNbConstitutiveLaws();
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);
+ auto & material = solid.getConstitutiveLaw(index);
for (auto index2 : arange(nb_phasefields)) {
- auto & phasefield = phase.getPhaseField(index2);
+ auto & phasefield = phase.getConstitutiveLaw(index2);
if (phasefield.getName() == material.getName()) {
auto & strain_on_qpoints = phasefield.getStrain();
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);
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);
Material::gradUToEpsilon<spatial_dimension>(grad_u, strain);
}
}
break;
}
}
}
}
/* -------------------------------------------------------------------------- */
void computeDamageOnQuadPoints(SolidMechanicsModel & solid,
PhaseFieldModel & phase, GhostType ghost_type) {
auto & fem = phase.getFEEngine();
auto & mesh = phase.getMesh();
- auto nb_materials = solid.getNbMaterials();
- auto nb_phasefields = phase.getNbPhaseFields();
+ auto nb_materials = solid.getNbConstitutiveLaws();
+ auto nb_phasefields = phase.getNbConstitutiveLaws();
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);
+ auto & material = solid.getConstitutiveLaw(index);
for (auto index2 : arange(nb_phasefields)) {
- auto & phasefield = phase.getPhaseField(index2);
+ auto & phasefield = phase.getConstitutiveLaw(index2);
if (phasefield.getName() == material.getName()) {
switch (spatial_dimension) {
case 1: {
auto & mat = dynamic_cast<MaterialDamage<1> &>(material);
auto & solid_damage = mat.getDamage();
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 = dynamic_cast<MaterialDamage<2> &>(material);
auto & solid_damage = mat.getDamage();
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 (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_phasefield_selector.cc b/test/test_model/test_phase_field_model/test_phasefield_selector.cc
index 12dad5367..e7727ac80 100644
--- a/test/test_model/test_phase_field_model/test_phasefield_selector.cc
+++ b/test/test_model/test_phase_field_model/test_phasefield_selector.cc
@@ -1,57 +1,56 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "phase_field_model.hh"
#include "phasefield_exponential.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
-
initialize("phasefield_selector.dat", argc, argv);
Math::setTolerance(1e-8);
Mesh mesh(1);
mesh.read("phasefield_selector.msh");
PhaseFieldModel model(mesh);
auto && selector = std::make_shared<MeshDataPhaseFieldSelector<std::string>>(
"physical_names", model);
model.setPhaseFieldSelector(selector);
model.initFull();
- PhaseField & chocolate = model.getPhaseField("chocolate");
- PhaseField & chewing_gum = model.getPhaseField("chewing-gum");
- PhaseField & candy = model.getPhaseField("candy");
+ const auto & chocolate = model.getPhaseField("chocolate");
+ const auto & chewing_gum = model.getPhaseField("chewing-gum");
+ const auto & candy = model.getPhaseField("candy");
- UInt chocolate_element = chocolate.getElementFilter(_segment_2)(0, 0);
- UInt chewing_gum_element = chewing_gum.getElementFilter(_segment_2)(0, 0);
- UInt candy_element = candy.getElementFilter(_segment_2)(0, 0);
+ auto chocolate_element = chocolate.getElementFilter(_segment_2)(0, 0);
+ auto chewing_gum_element = chewing_gum.getElementFilter(_segment_2)(0, 0);
+ auto candy_element = candy.getElementFilter(_segment_2)(0, 0);
if (chocolate_element != 0 || chewing_gum_element != 1 ||
candy_element != 2) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
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 130854381..381da86ac 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,83 +1,83 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 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"};
Int nb_surf = surfaces_name.size();
for (const auto & type :
mesh.elementTypes(spatial_dimension, _not_ghost, _ek_cohesive)) {
for (Int i = 0; i < nb_surf; ++i) {
auto expected_insertion = mesh.getElementGroup(surfaces_name[i])
.getElements(mesh.getFacetType(type))
.size();
- auto inserted_elements =
- model.getMaterial(surfaces_name[i]).getElementFilter()(type).size();
+ const auto & mat = model.getMaterial(surfaces_name[i]);
+ auto inserted_elements = mat.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_material_selector.cc b/test/test_model/test_solid_mechanics_model/test_material_selector.cc
index 00c5375a7..5135b14ab 100644
--- a/test/test_model/test_solid_mechanics_model/test_material_selector.cc
+++ b/test/test_model/test_solid_mechanics_model/test_material_selector.cc
@@ -1,53 +1,55 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "solid_mechanics_model.hh"
using namespace akantu;
int main(int argc, char * argv[]) {
initialize("material_selector.dat", argc, argv);
Math::setTolerance(1e-8);
Mesh mesh(1);
mesh.read("material_selector.msh");
SolidMechanicsModel model(mesh);
auto && selector = std::make_shared<MeshDataMaterialSelector<std::string>>(
"physical_names", model);
model.setMaterialSelector(selector);
model.initFull();
- Material & chocolate = model.getMaterial("chocolate");
- Material & chewing_gum = model.getMaterial("chewing-gum");
- Material & candy = model.getMaterial("candy");
+ const Material & chocolate = model.getMaterial("chocolate");
+ const Material & chewing_gum = model.getMaterial("chewing-gum");
+ const Material & candy = model.getMaterial("candy");
- UInt chocolate_element = chocolate.getElementFilter(_segment_2)(0, 0);
- UInt chewing_gum_element = chewing_gum.getElementFilter(_segment_2)(0, 0);
- UInt candy_element = candy.getElementFilter(_segment_2)(0, 0);
+ Int chocolate_element = chocolate.getElementFilter(_segment_2)(0, 0);
+ Int chewing_gum_element = chewing_gum.getElementFilter(_segment_2)(0, 0);
+ Int candy_element = candy.getElementFilter(_segment_2)(0, 0);
- if (chocolate_element != 0 || chewing_gum_element != 1 || candy_element != 2)
+ if (chocolate_element != 0 || chewing_gum_element != 1 ||
+ candy_element != 2) {
return EXIT_FAILURE;
+ }
return EXIT_SUCCESS;
}
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 bc02075e4..2776ea5ea 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,99 +1,91 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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) {
+ : Material(model, id), damage(this->registerInternal("damage", 1)) {
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;
- for (auto && data :
+ for (auto && [grad_u, sigma, dam] :
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);
-
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);
- 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);
+ for (auto && [grad_u, sigma, epot] :
+ zip(make_view(this->getGradU(el_type), dim, dim),
+ make_view(this->getStress(el_type), dim, dim),
+ this->potential_energy(el_type))) {
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 96e6b4289..89213fe69 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,108 +1,105 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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() override = default;
-
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public:
void initMaterial() override;
/// constitutive law for all element of a type
void computeStress(ElementType el_type,
GhostType ghost_type = _not_ghost) override;
/// constitutive law for a given quadrature point
- inline void computeStressOnQuad(MatrixProxy<Real> & grad_u,
- MatrixProxy<Real> & sigma, Real & damage);
+ template <class D1, class D2>
+ inline void computeStressOnQuad(Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & sigma, Real & dam);
/// compute the potential energy for all elements
void computePotentialEnergy(ElementType el_type) override;
/// compute the potential energy for on element
- inline void computePotentialEnergyOnQuad(MatrixProxy<Real> & grad_u,
- MatrixProxy<Real> & sigma,
+ template <class D1, class D2>
+ inline void computePotentialEnergyOnQuad(Eigen::MatrixBase<D1> & grad_u,
+ Eigen::MatrixBase<D2> & sigma,
Real & epot);
/* ------------------------------------------------------------------------ */
/* Accessors */
/* ------------------------------------------------------------------------ */
public:
/// compute the celerity of wave in the material
- inline Real getCelerity(const Element & element) const override;
+ [[nodiscard]] 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;
+ Real E{};
/// Poisson coefficient
- Real nu;
+ Real nu{};
/// First Lamé coefficient
- Real lambda;
+ Real lambda{};
/// Second Lamé coefficient (shear modulus)
- Real mu;
+ Real mu{};
/// resistance to damage
- Real Yd;
+ Real Yd{};
/// damage threshold
- Real Sd;
+ Real Sd{};
/// Bulk modulus
- Real kpa;
+ Real kpa{};
/// damage internal variable
- InternalField<Real> damage;
+ InternalField<Real> & damage;
};
-/* -------------------------------------------------------------------------- */
-/* inline functions */
-/* -------------------------------------------------------------------------- */
-#include "local_material_damage_inline_impl.hh"
-
} // namespace akantu
+#include "local_material_damage_inline_impl.hh"
+
#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 ba4798710..90de4e9d7 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,59 +1,71 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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" // NOLINT
+/* -------------------------------------------------------------------------- */
+
+#ifndef AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH__
+#define AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH__
+
+namespace akantu {
/* -------------------------------------------------------------------------- */
-inline void LocalMaterialDamage::computeStressOnQuad(MatrixProxy<Real> & grad_u,
- MatrixProxy<Real> & sigma,
- Real & dam) {
+template <class D1, class 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})
auto && epsilon = (grad_u + grad_u.transpose()) / 2.;
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) {
dam = (Y - Yd) / Sd;
}
dam = std::min(dam, 1.);
sigma *= 1 - dam;
}
/* -------------------------------------------------------------------------- */
+template <class D1, class D2>
inline void LocalMaterialDamage::computePotentialEnergyOnQuad(
- MatrixProxy<Real> & grad_u, MatrixProxy<Real> & sigma, Real & epot) {
+ Eigen::MatrixBase<D1> & grad_u, Eigen::MatrixBase<D2> & sigma,
+ Real & epot) {
epot = sigma.doubleDot(grad_u) / 2.;
}
/* -------------------------------------------------------------------------- */
inline Real
LocalMaterialDamage::getCelerity(const Element & /*element*/) const {
return (std::sqrt(E / rho));
}
+
+} // namespace akantu
+
+#endif /* AKANTU_LOCAL_MATERIAL_DAMAGE_INLINE_IMPL_HH__ */
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 f3dea4c39..c29fcb77e 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,244 +1,247 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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>>;
/*****************************************************************/
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) {
strain.zero();
strain(0, 0) = epsilon;
computeStressOnQuad(make_named_tuple("grad_u"_n = strain, "sigma"_n = sigma,
- "damage"_n = dam, "Ehat"_n = ehat));
+ "damage"_n = dam, "Ehat"_n = ehat,
+ "K0"_n = _K0));
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) {
strain.zero();
strain(0, 0) = epsilon;
strain(1, 1) = -this->nu * epsilon;
computeStressOnQuad(make_named_tuple("grad_u"_n = strain, "sigma"_n = sigma,
- "damage"_n = dam, "Ehat"_n = ehat));
+ "damage"_n = dam, "Ehat"_n = ehat,
+ "K0"_n = _K0));
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) {
strain.zero();
strain(0, 0) = epsilon;
strain(1, 1) = strain(2, 2) = -this->nu * epsilon;
computeStressOnQuad(make_named_tuple("grad_u"_n = strain, "sigma"_n = sigma,
- "damage"_n = dam, "Ehat"_n = ehat));
+ "damage"_n = dam, "Ehat"_n = ehat,
+ "K0"_n = _K0));
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 9e68fe5da..4ac409fb9 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,893 +1,895 @@
/**
* Copyright (©) 2017-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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> sigma(1, 1);
- Real sigma_th = 2;
+ Matrix<Real, 1, 1> eps{{2}};
+ Matrix<Real, 1, 1> sigma;
+ Real sigma_th = 2.;
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(
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(
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));
-
+ Real sigma_th = 0.;
Matrix<Real> rotation_matrix = getRandomRotation();
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, 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, 2, 2>::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;
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.lpNorm<Eigen::Infinity>() / sigma_expected.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<2>>::testEnergyDensity() {
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(
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, 3, 3> tangent;
/* Plane Strain */
// clang-format off
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(
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 = 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(
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, 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);
+ Real sigma_th{0.};
+
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));
Matrix<Real, 3, 3> sigma = this->reverseRotation(sigma_rot, rotation_matrix);
Matrix<Real, 3, 3> identity = Matrix<Real, 3, 3>::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, 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.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-14);
}
/* -------------------------------------------------------------------------- */
template <> void FriendMaterial<MaterialElastic<3>>::testEnergyDensity() {
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(
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,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(
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, 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() {
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
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, 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, 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, Dim, Dim> epsilon = (grad_u + grad_u.transpose()) / 2.;
// sigma_expected is computed directly in the *material* frame of reference
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.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<2>>::testEnergyDensity() {
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(
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(
make_named_tuple("tangent_moduli"_n = tangent));
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, 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, 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, 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() {
const Int Dim = 3;
// material frame of reference is rotate by rotation_matrix starting from
// canonical basis
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
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(
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, 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, Dim, Dim> epsilon = 0.5 * (grad_u + grad_u.transpose());
// sigma_expected is computed directly in the *material* frame of reference
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.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticOrthotropic<3>>::testEnergyDensity() {
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(
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
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);
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(
make_named_tuple("tangent_moduli"_n = tangent));
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
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);
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, 3, 3> C{{1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5}};
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, 3, 3> C{{1.0, 0.3, 0.4}, {0.3, 2.0, 0.1}, {0.4, 0.1, 1.5}};
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
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)
Matrix<Real, 2, 2> grad_u_rot =
this->reverseRotation(grad_u, rotation_matrix);
// stress in the canonical basis
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, 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, 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.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}};
Real epot = 0;
Real solution = 2.5;
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(
make_named_tuple("tangent_moduli"_n = tangent));
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, 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}};
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, 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}};
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, 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, 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, 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.lpNorm<Eigen::Infinity>();
EXPECT_NEAR(stress_error, 0., 1e-13);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testEnergyDensity() {
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(
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, 6, 6> tangent;
this->computeTangentModuliOnQuad(
make_named_tuple("tangent_moduli"_n = tangent));
Real tangent_error = (tangent - C).norm();
EXPECT_NEAR(tangent_error, 0, 1e-14);
}
/* -------------------------------------------------------------------------- */
template <>
void FriendMaterial<MaterialElasticLinearAnisotropic<3>>::testCelerity() {
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 3686c4441..c79f68b56 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,128 +1,127 @@
/**
* Copyright (©) 2019-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 += alpha(0);
for (auto p : arange(dim)) {
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);
refdis = alpha(0);
for (auto p : arange(dim)) {
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_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc
index c83116fdf..60f9b07f0 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,119 +1,119 @@
/**
* Copyright (©) 2010-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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);
Int max_steps = 1100;
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 = Matrix<Real, 2, 2>::Identity() * 5e7;
model.applyBC(BC::Neumann::FromHigherDim(stress), "Traction");
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 =
+ const auto & mat =
dynamic_cast<LocalMaterialDamage &>(model.getMaterial("concrete"));
const auto & filter = mat.getElementFilter();
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_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 ea608d359..f21c4aad1 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,89 +1,78 @@
/**
* Copyright (©) 2015-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 "aka_types.hh"
namespace akantu {
/* -------------------------------------------------------------------------- */
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);
-}
+ : MyNonLocalParent(model, id),
+ local_damage(this->registerInternal("local_damage", 1)),
+ damage(this->registerInternal("damage", 1)) {}
/* -------------------------------------------------------------------------- */
template <Int dim>
void CustomNonLocalTestMaterial<dim>::registerNonLocalVariables() {
/// register the non-local variable in the manager
- this->model.getNonLocalManager().registerNonLocalVariable(
+ this->getModel().getNonLocalManager().registerNonLocalVariable(
this->local_damage.getName(), this->damage.getName(), 1);
- this->model.getNonLocalManager()
+ this->getModel()
+ .getNonLocalManager()
.getNeighborhood(this->name)
.registerNonLocalVariable(damage.getName());
}
-/* -------------------------------------------------------------------------- */
-template <Int dim> void CustomNonLocalTestMaterial<dim>::initMaterial() {
- MyNonLocalParent::initMaterial();
-}
-
/* -------------------------------------------------------------------------- */
template <Int dim>
void CustomNonLocalTestMaterial<dim>::computeStress(ElementType el_type,
GhostType ghost_type) {
MyNonLocalParent::computeStress(el_type, ghost_type);
}
/* -------------------------------------------------------------------------- */
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);
+ for (auto && [stress, dam] :
+ zip(make_view<dim, dim>(this->stress(el_type, ghost_type)),
+ this->damage(el_type, ghost_type))) {
+ stress = stress * (1. - dam);
}
}
/* -------------------------------------------------------------------------- */
// Instantiate the material for the 3 dimensions
template class CustomNonLocalTestMaterial<1>;
template class CustomNonLocalTestMaterial<2>;
template class CustomNonLocalTestMaterial<3>;
-static bool material_is_allocated_custom_non_local_test_material =
- instantiateMaterial<CustomNonLocalTestMaterial>(
+const bool material_is_allocated_custom_non_local_test_material
+ [[maybe_unused]] = 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 07242b42b..caecae0b8 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,70 +1,67 @@
/**
* Copyright (©) 2012-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 <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 (const auto & type :
- this->element_filter.elementTypes(dim, ghost_type)) {
+ this->getElementFilter().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;
+ 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_solid_mechanics_model_reassign_material.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_reassign_material.cc
index 69e27fd54..95579922e 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,185 +1,185 @@
/**
* Copyright (©) 2014-2023 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* This file is part of Akantu
*
* Akantu is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Akantu is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You 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 {
+class StraightInterfaceMaterialSelector : public ConstitutiveLawSelector {
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) {
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);
}
Int operator()(const Element & elem) override {
if (not materials_set) {
setMaterials();
}
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)) {
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
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();
+ model.reassignConstitutiveLaw();
}
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.;
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/third-party/akantu_iterators/CMakeLists.txt b/third-party/akantu_iterators/CMakeLists.txt
index a7f38da02..467bb884c 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)
+cmake_minimum_required(VERSION 3.9)
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 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/include/aka_compatibilty_with_cpp_standard.hh b/third-party/akantu_iterators/include/aka_compatibilty_with_cpp_standard.hh
index 40bbf93a9..2edf52cfa 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,225 +1,227 @@
/**
* @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/>.
*
*/
/* -------------------------------------------------------------------------- */
+#if __cplusplus < 201703L
#include "aka_static_if.hh"
+#endif
/* -------------------------------------------------------------------------- */
#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>
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(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_named_tuple.hh b/third-party/akantu_iterators/include/aka_named_tuple.hh
index 74c231976..1ee239cbf 100644
--- a/third-party/akantu_iterators/include/aka_named_tuple.hh
+++ b/third-party/akantu_iterators/include/aka_named_tuple.hh
@@ -1,311 +1,312 @@
/**
* @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");
+ static_assert((index != Index(-1) and is_named_tag_v<NT>),
+ "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 15424c3c1..aab2a026c 100644
--- a/third-party/akantu_iterators/include/aka_str_hash.hh
+++ b/third-party/akantu_iterators/include/aka_str_hash.hh
@@ -1,175 +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
-// 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/iterators/aka_filter_iterator.hh b/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh
index c657ecf68..2e0dfb66c 100644
--- a/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh
+++ b/third-party/akantu_iterators/include/iterators/aka_filter_iterator.hh
@@ -1,346 +1,345 @@
/**
* @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_HH
#define AKA_FILTER_ITERATOR_HH
#ifndef AKANTU_ITERATORS_NAMESPACE
#define AKANTU_ITERATORS_NAMESPACE akantu
#endif
namespace AKANTU_ITERATORS_NAMESPACE {
/* -------------------------------------------------------------------------- */
namespace iterators AKA_ITERATOR_EXPORT_NAMESPACE {
template <class filter_iterator_t, class container_iterator_t>
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 = 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 = 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,
const container_iterator_t & container_begin)
: filter_it(std::move(filter_it)), container_begin(container_begin),
container_it(container_begin) {}
auto operator++() -> FilterIterator & {
++filter_it;
return *this;
}
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;
}
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;
}
// 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;
}
// 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>
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));
}
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)
+ FilterIfIterator(container_iterator_t && container_begin,
+ 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 iterators 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");
}
auto begin() const -> decltype(auto) {
return iterators::make_filter_iterator(filter.begin(), container.begin());
}
auto begin() -> decltype(auto) {
return iterators::make_filter_iterator(filter.begin(), container.begin());
}
auto end() const -> decltype(auto) {
return iterators::make_filter_iterator(filter.end(), container.begin());
}
auto end() -> decltype(auto) {
return iterators::make_filter_iterator(filter.end(), container.begin());
}
private:
filter_t filter;
Container container;
};
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)) {}
+ : container(container), 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
+} // namespace containers AKA_ITERATOR_EXPORT_NAMESPACE
template <class filter_t, class 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_HH
diff --git a/third-party/akantu_iterators/test/test_tuples.cc b/third-party/akantu_iterators/test/test_tuples.cc
index 3f6979a6d..0a1b34ec3 100644
--- a/third-party/akantu_iterators/test/test_tuples.cc
+++ b/third-party/akantu_iterators/test/test_tuples.cc
@@ -1,137 +1,138 @@
/**
* @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);
+// 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, 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));
-}
+// EXPECT_EQ(47, std::get<1>(tuple));
+// }
-TEST(NamedTuples, StdGet) {
- const auto tuple = make_named_tuple(get<"a"_h>() = 1, get<"b"_h>() = 2);
+// 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));
-}
+// 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);
+// 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);
+// 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));
-}
+// 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);
+// 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));
-}
+// 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);
+// 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);
+// 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));
-}
+// 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));
+// 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)>();
+// 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");
+// 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);
-}
+// 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, MixGNUExtensionHash) {
- const auto tuple =
- make_named_tuple("nom"_n = 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));
-}
+// 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/iohelper/CMakeLists.txt b/third-party/iohelper/CMakeLists.txt
index 0cfe0d4ca..4f7234b44 100644
--- a/third-party/iohelper/CMakeLists.txt
+++ b/third-party/iohelper/CMakeLists.txt
@@ -1,81 +1,74 @@
#===============================================================================
# @file CMakeLists.txt
#
# @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
#
# @date creation: Thu Oct 11 2012
# @date last modification: Fri Jun 13 2014
#
# @brief main configuration file
#
# @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/>.
#
#===============================================================================
#===============================================================================
# CMake Project
#===============================================================================
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.9)
project(IOHelper)
enable_language(CXX)
#===============================================================================
# Misc.
#===============================================================================
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries.")
-find_package (ZLIB)
-
-if(ZLIB_FOUND)
- set (IOHELPER_EXTERNAL_LIBS ${IOHELPER_EXTERNAL_LIBS} ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIR})
-endif()
-
#===============================================================================
# Version Number
#===============================================================================
# IOHelper version number. An even minor number corresponds to releases.
set(IOHELPER_MAJOR_VERSION 1)
set(IOHELPER_MINOR_VERSION 1)
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeVersionGenerator.cmake)
#define_project_version()
#==============================================================================
# Library
#===============================================================================
add_subdirectory(src)
#==============================================================================
# Packaging
#===============================================================================
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/IOHelperCPack.cmake)
#===============================================================================
# Tests
#===============================================================================
option(IOHELPER_TESTS "Activate tests" OFF)
if(IOHELPER_TESTS)
enable_testing()
include(CTest)
add_subdirectory(test)
endif()
diff --git a/third-party/iohelper/src/CMakeLists.txt b/third-party/iohelper/src/CMakeLists.txt
index 98881702d..e09673b90 100644
--- a/third-party/iohelper/src/CMakeLists.txt
+++ b/third-party/iohelper/src/CMakeLists.txt
@@ -1,114 +1,111 @@
#===============================================================================
# @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 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/base64.hh b/third-party/iohelper/src/base64.hh
index 555a37dbe..646fad1cd 100644
--- a/third-party/iohelper/src/base64.hh
+++ b/third-party/iohelper/src/base64.hh
@@ -1,437 +1,422 @@
/**
* @file base64.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
* @author Nicolas Richart <nicolas.richart@epfl.ch>
*
* @date creation: Thu Mar 11 2010
* @date last modification: Wed Nov 13 2013
*
* @brief header for base64 handling
*
*
* 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 free software: you can redistribute it and/or modify it under
+ * the terms of the GNU 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_BASE64_H_
#define IOHELPER_BASE64_H_
/* -------------------------------------------------------------------------- */
-#include <vector>
#include "file_manager.hh"
-#ifdef USING_ZLIB
-#include <zlib.h>
-#endif
+#include <vector>
/* -------------------------------------------------------------------------- */
namespace iohelper {
#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)
/** Class that allow to push binary data
in base64 format to any file.
This class is mainly used by the paraview helper
to create binary XML VTK files.
The conversion is a 4/3 size conversion. */
-
-class Base64Writer{
+class Base64Writer {
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
- public:
-
+public:
Base64Writer(File & f);
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
- //! for any packet in base64 a little header is used that is an int = nbBytes written
+ //! for any packet in base64 a little header is used that is an int = nbBytes
+ //! written
void WriteHeader();
//! this is used to allocate the memory for the final count of bytes
void CreateHeader();
//! when all stream is ready buffer is sent to file
inline void DumpToFile();
//! empty temporary buffer
void ClearBuffer();
template <typename T> inline void push(T t);
//! notify that we don't want to add any data. Closing the current buffer
void finish();
//! decode 3 bytes from 4 Base64 bytes (4/3 ratio)
- int Decode(char c0,char c1,char c2,char c3,
- char * r0,char * r1,char * r2);
+ int Decode(char c0, char c1, char c2, char c3, char * r0, char * r1,
+ char * r2);
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
- private:
+private:
//! push to file a Byte
inline void PushByteInBase64(unsigned char c);
//! when 4 bytes are ready they are dumped to buffer by this function
inline void dumpToBuffer();
//! initialisation process
inline void InitBase64Stuff();
//! primitive function to push bytes to file
- //void ochar(int c);
+ // void ochar(int c);
//! decoding table
char dtable[256];
//! encoding table
char etable[256];
//! stage in conversion process(1,2 or 3)
int n;
//! used to code/decode
- unsigned char igroup[3],ogroup[4];
+ unsigned char igroup[3], ogroup[4];
- //!unused
+ //! unused
int linelength;
- //!unused
+ //! unused
// int maxlinelength;
//! LM file descriptor
File & file;
//! buffer to cache data
std::vector<unsigned char> buffer;
//! number of bytes written to buffer
long nbBytes;
//! for rewind need o floating index
int start;
-
};
/* -------------------------------------------------------------------------- */
-template<typename T> inline void Base64Writer::push(T t) {
+template <typename T> inline void Base64Writer::push(T t) {
auto * c = (unsigned char *)&t;
- for (unsigned int i = 0 ; i < sizeof(T) ; ++i){
+ for (unsigned int i = 0; i < sizeof(T); ++i) {
this->PushByteInBase64(c[i]);
}
}
-template<> inline void Base64Writer::push<char *>(char * t) {
+template <> inline void Base64Writer::push<char *>(char * t) {
auto * c = (unsigned char *)t;
- for (unsigned int i = 0 ; i < 512 ; ++i){
+ for (unsigned int i = 0; i < 512; ++i) {
if (t[i] == '\0') {
break;
}
PushByteInBase64(c[i]);
}
}
-inline void Base64Writer::InitBase64Stuff(){
- memset(dtable,0xFF,256);
- memset(etable,0xFF,256);
-
- for(int i=0;i<9;i++){
- etable[i]= (char)('A'+i);
- dtable[0+etable[i]] = (char)i;
- etable[i+9]= (char)('J'+i);
- dtable[(0+etable[i+9])] = (char)(i+9);
- etable[26+i]= (char)('a'+i);
- dtable[(0+etable[26+i])] = (char)(i + 26);
- etable[(26+i+9)]= (char)('j'+i);
- dtable[(0+etable[26+i+9])] = (char)(i + 26 + 9);
+inline void Base64Writer::InitBase64Stuff() {
+ memset(dtable, 0xFF, 256);
+ memset(etable, 0xFF, 256);
+
+ for (int i = 0; i < 9; i++) {
+ etable[i] = (char)('A' + i);
+ dtable[0 + etable[i]] = (char)i;
+ etable[i + 9] = (char)('J' + i);
+ dtable[(0 + etable[i + 9])] = (char)(i + 9);
+ etable[26 + i] = (char)('a' + i);
+ dtable[(0 + etable[26 + i])] = (char)(i + 26);
+ etable[(26 + i + 9)] = (char)('j' + i);
+ dtable[(0 + etable[26 + i + 9])] = (char)(i + 26 + 9);
}
- for(int i= 0;i<8;i++){
- etable[i+18]= (char)('S'+i);
- dtable[(0+etable[i+18])] = (char)(i + 18);
- etable[26+i+18]= (char)('s'+i);
- dtable[(0+etable[26+i+18])] = (char)(26 + i + 18);
+ for (int i = 0; i < 8; i++) {
+ etable[i + 18] = (char)('S' + i);
+ dtable[(0 + etable[i + 18])] = (char)(i + 18);
+ etable[26 + i + 18] = (char)('s' + i);
+ dtable[(0 + etable[26 + i + 18])] = (char)(26 + i + 18);
}
- for(char i= 0;i<10;i++){
- etable[52+i]= (char)('0'+i);
- dtable[(0+etable[i+52])] = (char)(i + 52);
+ for (char i = 0; i < 10; i++) {
+ etable[52 + i] = (char)('0' + i);
+ dtable[(0 + etable[i + 52])] = (char)(i + 52);
}
- etable[62]= '+';
- dtable[0+etable[62]] = 62;
- etable[63]= '/';
- dtable[0+etable[63]] = 63;
+ etable[62] = '+';
+ dtable[0 + etable[62]] = 62;
+ etable[63] = '/';
+ dtable[0 + etable[63]] = 63;
}
/* -------------------------------------------------------------------------- */
-
// inline void Base64Writer::PushIntegerInBase64(int d){
// // DUMP("pushing " << d << " ( n = " << n << " )",DBG_ALL);
// unsigned char * c = (unsigned char*)&d;
// for (unsigned int i = 0 ; i < sizeof(int) ; ++i){
// PushByteInBase64(c[i]);
// }
// }
-// /* -------------------------------------------------------------------------- */
-
+// /* --------------------------------------------------------------------------
+// */
// inline void Base64Writer::PushStrInBase64(char * str){
// unsigned char * c = (unsigned char*)str;
// for (unsigned int i = 0 ; i < 512 ; ++i){
// if (str[i] == '\0') break;
// PushByteInBase64(c[i]);
// }
// }
-// /* -------------------------------------------------------------------------- */
-
+// /* --------------------------------------------------------------------------
+// */
// inline void Base64Writer::PushDoubleInBase64(double d){
-// // DUMP("pushing double " << d << " as " << sizeof(double) << " bytes",DBG_ALL);
+// // DUMP("pushing double " << d << " as " << sizeof(double) << "
+// bytes",DBG_ALL);
// unsigned char * c = (unsigned char*)&d;
// for (unsigned int i = 0 ; i < sizeof(double) ; ++i){
// PushByteInBase64(c[i]);
// }
// }
-// /* -------------------------------------------------------------------------- */
+// /* --------------------------------------------------------------------------
+// */
+inline void Base64Writer::PushByteInBase64(unsigned char c) {
+ // initialise les blocs
+ // DUMP("pushing byte " << (int) c << " at position " << n,DBG_ALL);
-inline void Base64Writer::PushByteInBase64(unsigned char c){
- //initialise les blocs
- // DUMP("pushing byte " << (int) c << " at position " << n,DBG_ALL);
-
- if (n == 0){
- igroup[0]= 0;
- igroup[1]= 0;
- igroup[2]= 0;
+ if (n == 0) {
+ igroup[0] = 0;
+ igroup[1] = 0;
+ igroup[2] = 0;
}
- igroup[n]= c;
+ igroup[n] = c;
++n;
- if(n == 3){
+ if (n == 3) {
dumpToBuffer();
}
nbBytes += 1;
}
/* -------------------------------------------------------------------------- */
-
-inline void Base64Writer::finish(){
+inline void Base64Writer::finish() {
if (n == 0) {
return;
}
dumpToBuffer();
linelength = 0;
}
/* -------------------------------------------------------------------------- */
-
-inline void Base64Writer::dumpToBuffer(){
- if(n<3){
- igroup[2]= 0;
- if(n<2){
- igroup[1]= 0;
+inline void Base64Writer::dumpToBuffer() {
+ if (n < 3) {
+ igroup[2] = 0;
+ if (n < 2) {
+ igroup[1] = 0;
}
}
- //DUMP("premiere partie en base 64 : " << (igroup[0]>>2),DBG_ALL);
- int index = igroup[0]>>2;
- ogroup[0]= etable[index];
- //DUMP("deuxieme partie en base 64 : " << (((igroup[0]&3)<<4)|(igroup[1]>>4)),DBG_ALL);
- index = ((igroup[0]&3)<<4)|(igroup[1]>>4);
- ogroup[1]= etable[index];
- //DUMP("troisieme partie en base 64 : " << (((igroup[1]&0xF)<<2)|(igroup[2]>>6)),DBG_ALL);
- index = ((igroup[1]&0xF)<<2)|(igroup[2]>>6);
- ogroup[2]= etable[index];
- //DUMP("last partie en base 64 : " << (igroup[2]&0x3F),DBG_ALL);
- index = igroup[2]&0x3F;
- ogroup[3]= etable[index];
-
- if(n<3){
- ogroup[3]= '=';
- if(n<2){
- ogroup[2]= '=';
+ // DUMP("premiere partie en base 64 : " << (igroup[0]>>2),DBG_ALL);
+ int index = igroup[0] >> 2;
+ ogroup[0] = etable[index];
+ // DUMP("deuxieme partie en base 64 : " <<
+ // (((igroup[0]&3)<<4)|(igroup[1]>>4)),DBG_ALL);
+ index = ((igroup[0] & 3) << 4) | (igroup[1] >> 4);
+ ogroup[1] = etable[index];
+ // DUMP("troisieme partie en base 64 : " <<
+ // (((igroup[1]&0xF)<<2)|(igroup[2]>>6)),DBG_ALL);
+ index = ((igroup[1] & 0xF) << 2) | (igroup[2] >> 6);
+ ogroup[2] = etable[index];
+ // DUMP("last partie en base 64 : " << (igroup[2]&0x3F),DBG_ALL);
+ index = igroup[2] & 0x3F;
+ ogroup[3] = etable[index];
+
+ if (n < 3) {
+ ogroup[3] = '=';
+ if (n < 2) {
+ ogroup[2] = '=';
}
}
- for(int i= 0;i<4;i++){
- //DUMP("dumped to buffer " << ogroup[i],DBG_ALL);
+ for (int i = 0; i < 4; i++) {
+ // DUMP("dumped to buffer " << ogroup[i],DBG_ALL);
if (start == -1) {
buffer.push_back(ogroup[i]);
} else {
buffer[start] = ogroup[i];
++start;
}
}
- //remise a zero du compteur
- n = 0;
+ // remise a zero du compteur
+ n = 0;
}
/* inline void Base64Writer::ochar(int c) */
/* { */
/* if(file.dumpchar(c)==-1){ */
-/* FATAL("error while writing to file (in compressed mode) ! no more space ?"); */
+/* FATAL("error while writing to file (in compressed mode) ! no more space
+ * ?"); */
/* } */
/* linelength++; */
/* } */
/* -------------------------------------------------------------------------- */
+inline int Base64Writer::Decode(char c0, char c1, char c2, char c3, char * r0,
+ char * r1, char * r2) {
+ auto d0 = dtable[0 + c0];
+ auto d1 = dtable[0 + c1];
+ auto d2 = dtable[0 + c2];
+ auto d3 = dtable[0 + c3];
-inline int Base64Writer::Decode(char c0,char c1,char c2,char c3,
- char * r0,char * r1,char * r2){
- auto d0 = dtable[0+c0];
- auto d1 = dtable[0+c1];
- auto d2 = dtable[0+c2];
- auto d3 = dtable[0+c3];
-
- //DUMP("d0 " << (int)d0 << " d1 " << (int)d1 << " d2 " << (int)d2 << " d3 " << (int)d3,DBG_ALL);
+ // DUMP("d0 " << (int)d0 << " d1 " << (int)d1 << " d2 " << (int)d2 << " d3 "
+ // << (int)d3,DBG_ALL);
// Decode the 3 bytes
*r0 = (char)(((d0 << 2) & 0xFC) | ((d1 >> 4) & 0x03));
*r1 = (char)(((d1 << 4) & 0xF0) | ((d2 >> 2) & 0x0F));
*r2 = (char)(((d2 << 6) & 0xC0) | ((d3 >> 0) & 0x3F));
- //DUMP("r0 " << (int)*r0 << " r1 " << (int)*r1 << " r2 " << (int)*r2,DBG_ALL);
+ // DUMP("r0 " << (int)*r0 << " r1 " << (int)*r1 << " r2 " <<
+ // (int)*r2,DBG_ALL);
// Return the number of bytes actually decoded
- if (c2 == '=')
- {
+ if (c2 == '=') {
return 1;
- }
- if (c3 == '=')
- {
+ }
+ if (c3 == '=') {
return 2;
- }
+ }
return 3;
}
/* -------------------------------------------------------------------------- */
-
-
-inline void Base64Writer::WriteHeader(){
+inline void Base64Writer::WriteHeader() {
// if (bflag == BASE64){
// char byteC[8];
char byte[6];
finish();
-/* long save_offset; */
+ /* long save_offset; */
+ /* save_offset = file.tell(); */
+ /* file.seek(header_offset,SEEK_SET); */
+ /* //reread the 4 bytes precedently written */
-/* save_offset = file.tell(); */
-/* file.seek(header_offset,SEEK_SET); */
-/* //reread the 4 bytes precedently written */
+ /* file.read(byteC,sizeof(char),4); */
-/* file.read(byteC,sizeof(char),4); */
+ /* DUMP("la chaine saisie " << byteC[0] << " " << byteC[1] << " " <<
+ * byteC[2] << " " << byteC[3]); */
+ /* b64.Decode(byteC[0],byteC[0],byteC[0],byteC[0], */
+ /* byte,byte+1,byte+2); */
+ // DUMP("la chaine saisie " << buffer[0] << " " << buffer[1] << " " <<
+ // buffer[2] << " " << buffer[3],DBG_ALL);
-/* DUMP("la chaine saisie " << byteC[0] << " " << byteC[1] << " " << byteC[2] << " " << byteC[3]); */
-/* b64.Decode(byteC[0],byteC[0],byteC[0],byteC[0], */
-/* byte,byte+1,byte+2); */
- //DUMP("la chaine saisie " << buffer[0] << " " << buffer[1] << " " << buffer[2] << " " << buffer[3],DBG_ALL);
+ Decode(buffer[0], buffer[0], buffer[0], buffer[0], byte, byte + 1, byte + 2);
- Decode(buffer[0], buffer[0], buffer[0], buffer[0],
- byte, byte + 1, byte + 2);
+ /* file.read(byteC+4,sizeof(char),4); */
+ /* DUMP("la chaine saisie " << byteC[4] << " " << byteC[5] << " " <<
+ * byteC[6] << " " << byteC[7]); */
+ /* int nb = b64.Decode(byteC[4],byteC[5],byteC[6],byteC[7], */
+ /* byte+3,byte+4,byte+5); */
-/* file.read(byteC+4,sizeof(char),4); */
-/* DUMP("la chaine saisie " << byteC[4] << " " << byteC[5] << " " << byteC[6] << " " << byteC[7]); */
-/* int nb = b64.Decode(byteC[4],byteC[5],byteC[6],byteC[7], */
-/* byte+3,byte+4,byte+5); */
+ // DUMP("la chaine saisie " << buffer[4] << " " << buffer[5] << " " <<
+ // buffer[6] << " " << buffer[7],DBG_ALL);
+ int nb = Decode(buffer[4], buffer[5], buffer[6], buffer[7], byte + 3,
+ byte + 4, byte + 5);
- //DUMP("la chaine saisie " << buffer[4] << " " << buffer[5] << " " << buffer[6] << " " << buffer[7],DBG_ALL);
- int nb = Decode(buffer[4],buffer[5],buffer[6],buffer[7],
- byte + 3,byte + 4,byte + 5);
+ /* //je me replace au debut du header */
+ /* file.seek(header_offset,SEEK_SET); */
+ /* //je viens de relire 6 octets */
+ /* //les quatres premiers seulement sont a changer */
-
-/* //je me replace au debut du header */
-/* file.seek(header_offset,SEEK_SET); */
-/* //je viens de relire 6 octets */
-/* //les quatres premiers seulement sont a changer */
-
-
- //DUMP("placing number of writen bytes : " << nbBytes << " " << buffer.size(),DBG_ALL);
+ // DUMP("placing number of writen bytes : " << nbBytes << " " <<
+ // buffer.size(),DBG_ALL);
auto temp = static_cast<int>(nbBytes);
start = 0;
push(temp);
if (nb > 1) {
push(byte[4]);
}
if (nb > 2) {
push(byte[5]);
}
start = -1;
nbBytes = temp;
finish();
DumpToFile();
}
/* -------------------------------------------------------------------------- */
-
-inline void Base64Writer::DumpToFile(){
- file.write((char*)&buffer[0],buffer.size());
+inline void Base64Writer::DumpToFile() {
+ file.write((char *)&buffer[0], buffer.size());
}
/* -------------------------------------------------------------------------- */
-
-inline void Base64Writer::ClearBuffer(){
+inline void Base64Writer::ClearBuffer() {
buffer.clear();
nbBytes = 0;
}
/* -------------------------------------------------------------------------- */
-
-inline void Base64Writer::CreateHeader(){
+inline void Base64Writer::CreateHeader() {
ClearBuffer();
push<int>(0);
}
/* -------------------------------------------------------------------------- */
-inline Base64Writer::Base64Writer(File & f):
- file(f){
+inline Base64Writer::Base64Writer(File & f) : file(f) {
linelength = 0;
InitBase64Stuff();
n = 0;
start = -1;
igroup[0] = 0;
igroup[1] = 0;
igroup[2] = 0;
ogroup[0] = 0;
ogroup[1] = 0;
ogroup[2] = 0;
ogroup[3] = 0;
}
/* -------------------------------------------------------------------------- */
#if defined(__INTEL_COMPILER)
/// remark #981: operands are evaluated in unspecified order
-#pragma warning ( pop )
-#endif //defined(__INTEL_COMPILER)
-
-
-
-
-}
-
+#pragma warning(pop)
+#endif // defined(__INTEL_COMPILER)
+} // namespace iohelper
#endif /* IOHELPER_BASE64_H_ */
diff --git a/third-party/iohelper/src/file_manager.hh b/third-party/iohelper/src/file_manager.hh
index 6ea8fa981..61bb41f0e 100644
--- a/third-party/iohelper/src/file_manager.hh
+++ b/third-party/iohelper/src/file_manager.hh
@@ -1,350 +1,83 @@
/**
* @file file_manager.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date creation: Thu Mar 11 2010
* @date last modification: Thu Dec 06 2012
*
* @brief file manager header
*
*
* 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_FILE_MANAGER_H_
#define IOHELPER_FILE_MANAGER_H_
/* -------------------------------------------------------------------------- */
-#include <zlib.h>
-#include <stdio.h>
+#include "iohelper_common.hh"
+#include <fstream>
+#include <iostream>
#include <stdarg.h>
+#include <stdio.h>
#include <string>
-#include <iostream>
-#include <fstream>
#include <typeinfo>
-#include "iohelper_common.hh"
/* -------------------------------------------------------------------------- */
namespace iohelper {
-template <class charT, class Traits=std::char_traits<charT> >
-class GZfstream : public std::basic_fstream<charT,Traits> {
-
- /* ------------------------------------------------------------------------ */
- /* Constructors/Destructors */
- /* ------------------------------------------------------------------------ */
+template <class charT, class Traits = std::char_traits<charT>>
+class GZfstream : public std::basic_fstream<charT, Traits> {
public:
-
GZfstream();
GZfstream(const std::string & fname,
- std::fstream::openmode mode = std::fstream::out,
- bool compr=false);
-
- /* ------------------------------------------------------------------------ */
- /* Methods */
- /* ------------------------------------------------------------------------ */
+ std::fstream::openmode mode = std::fstream::out,
+ bool compr = false);
///! opening methods
inline void open(const std::string & name,
- std::fstream::openmode mode = std::fstream::out,
- bool compr= false);
- // inline void close();
-
- // // //! writing methods
- // template <typename T> GZfstream & operator << (const T & v);
- // inline GZfstream & operator << (std::ostream& (*op)(std::ostream&)){};
- // inline GZfstream & write(const void * buffer,std::streamsize n);
- // inline GZfstream & flush();
- // // //! reading methods
- // template <typename T> GZfstream & operator >> (T & v);
- // inline GZfstream & read(void * buffer,std::streamsize n);
-
- /* ------------------------------------------------------------------------ */
- /* Class Members */
- /* ------------------------------------------------------------------------ */
-
-
- private:
-
-// #ifdef USING_ZLIB
-// gzFile gzfile;
-// #endif
-
-// int compressed;
+ std::fstream::openmode mode = std::fstream::out,
+ bool compr = false);
+private:
};
-
-// /* -------------------------------------------------------------------------- */
-
-
template <class charT, class Traits>
- inline GZfstream<charT,Traits>::GZfstream():
- std::basic_fstream<charT,Traits>(){
-// compressed = 0;
-// #ifdef USING_ZLIB
-// gzfile = NULL;
-// #endif
-}
-
-// /* -------------------------------------------------------------------------- */
+inline GZfstream<charT, Traits>::GZfstream()
+ : std::basic_fstream<charT, Traits>() {}
template <class charT, class Traits>
inline GZfstream<charT, Traits>::GZfstream(const std::string & fname,
std::fstream::openmode mode,
bool /*unused*/)
- : std::basic_fstream<charT, Traits>(fname.c_str(), mode) {
- // compressed = compr;
-// #ifdef USING_ZLIB
-// gzfile = NULL;
-// #endif
-// open(fname,mode,compressed);
-}
-
-// /* -------------------------------------------------------------------------- */
-
-// // inline void GZfstream::printf(const std::string & formated, ...){
-// // if (!opened) {
-// // FATAL("Warning : file not opened " << name);
-// // }
-
-
-// // // if (!opened) return;
-
-// // if (_file == NULL) FATAL("fichier non ouvert mais ce n'est pas normal");
-
-// // char buf[512];
-
-// // va_list list;
-// // va_start(list,formated);
-// // int len = vsprintf(buf,formated.c_str(),list);
-// // va_end(list);
-
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // gzwrite(gzfile,buf,len);
-// // return;
-// // }
-// // else
-// // #endif
-// // fwrite(buf,len,1,_file);
-
-// // }
-
-// /* -------------------------------------------------------------------------- */
-
-
-// // inline void GZfstream::gets(std::string & buf){
-// // char * ret;
-// // const UInt len = 255;
-// // char buffer[len] = "";
-
-// // if (!opened) {
-// // FATAL("Warning : file not opened " << name);
-// // }
-// // if (_file == NULL) FATAL("file not opened: exit");
-
-// // DUMP("read to buf (" << buf << ") at most " << len << " characters");
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // ret = gzgets(gzfile,buffer,len);
-// // }
-// // else
-// // #endif
-// // ret = fgets(buffer,len,_file);
-
-// // if (ret == NULL) throw;
-
-// // DUMP("read to buf (" << buf << ") at most " << len << " characters");
-
-// // buf = buffer;
-// // }
-
-// /* -------------------------------------------------------------------------- */
-
-
-// template <class charT, class Traits>
-// inline void GZfstream<charT,Traits>::close(){
-
-// #ifdef USING_ZLIB
-// if (this->is_open() && compressed){
-// gzclose(gzfile);
-// gzfile = NULL;
-// }
-// #endif
-// }
-
-// /* -------------------------------------------------------------------------- */
+ : std::basic_fstream<charT, Traits>(fname.c_str(), mode) {}
template <class charT, class Traits>
inline void GZfstream<charT, Traits>::open(const std::string & fname,
std::fstream::openmode mode,
bool /*unused*/) {
- std::basic_fstream<charT,Traits>::open(fname.c_str(),mode);
-
-// if (this->is_open()) this->close();
-
-// compressed = compr;
-// this->open(fname.c_str(),mode);
-// if (!this->is_open()) FATAL("Could not open file "<< fname);
-
-// #ifdef USING_ZLIB
-// if (compressed){
-// std::stringstream _mode;
-// if (mode & std::fstream::in) _mode << "r";
-// if (mode & std::fstream::out) _mode << "w";
-// if (mode & std::fstream::app) _mode << "a";
-// if (mode & std::fstream::binary) _mode << "b";
-
-// std::cerr << typeid(*this->rdbuf()).name() << std::endl;
-// int fd = this->rdbuf()->_M_file->fd();
-
-// //gzfile = gzdopen(this->rdbuf()->fd(),_mode.str().c_str());
-// throw;
-// }
-// #endif
-
-// DUMP("file " << name << " opened , compressed = " << compressed);
+ std::basic_fstream<charT, Traits>::open(fname.c_str(), mode);
}
-// /* -------------------------------------------------------------------------- */
-
-
-// // inline int GZfstream::dumpchar(int c){
-// // if (!opened) {
-// // FATAL("Warning : file not opened " << name);
-// // }
-
-// // // if (!opened) return EOF;
-
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // int res = gzputc(gzfile,c);
-// // //DUMP("file opened in compressed form " << name);
-// // if (c != res)
-// // FATAL("j'ai pas ecrit ce que je voulais (compressed) " << res);
-// // return res;
-// // }
-// // else
-// // #endif
-// // if (c != putc(c,_file))
-// // FATAL("j'ai pas ecrit ce que je voulais");
-// // return c;
-// // }
-// /* -------------------------------------------------------------------------- */
-
-
-
-// // inline int GZfstream::seek(int offset,int set){
-// // if (!opened) {
-// // FATAL("Warning : file not opened " << name);
-// // }
-
-
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // return gzseek(gzfile, offset,set);
-// // }
-// // else
-// // #endif
-// // return fseek(_file,offset,set);
-// // }
-
-// // /* -------------------------------------------------------------------------- */
-
-
-// // inline int GZfstream::tell(){
-// // if (!opened) {
-// // FATAL("Warning : file not opened " << name);
-// // }
-
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // return gztell(gzfile);
-// // }
-// // else
-// // #endif
-
-// // return ftell(_file);
-// // }
-
-// // /* -------------------------------------------------------------------------- */
-
-// //template <class charT, class Traits>
-// //inline GZfstream<charT,Traits> & GZfstream<charT,Traits>::read(void * buffer,
-// // std::streamsize size){
-// // if (!opened) {
-// // FATAL("Warning : file not opened " << name);
-// // }
-
-
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // return gzread(gzfile,buffer,size*number);
-// // }
-// // else
-// // #endif
-// // return fread(buffer,size,number,_file);
-// //}
-
-// /* -------------------------------------------------------------------------- */
-
-
-// // template <class charT, class Traits>
-// // inline GZfstream<charT,Traits> & GZfstream<charT,Traits>::write(const void * buffer,
-// // std::streamsize size){
-// // // if (!this->is_open()) throw std::ios_base::failure("file not opened");
-
-// // Int nwrite;
-// // #ifdef USING_ZLIB
-// // if (compressed) nwrite = gzwrite(gzfile,buffer,size);
-// // else
-// // #endif
-// // this->write(buffer,size);
-
-// // // if (nwrite == 0) throw std::ios_base::failure("could not write any byte");
-
-// // return *this;
-// // }
-
-// /* -------------------------------------------------------------------------- */
-
-
-// // template <class charT, class Traits>
-// // inline GZfstream<charT,Traits> & GZfstream<charT,Traits>::flush(){
-// // // if (!this->is_open()) throw std::ios_base::failure("file not opened");
-
-// // #ifdef USING_ZLIB
-// // if (compressed){
-// // gzflush(gzfile,Z_SYNC_FLUSH);
-// // }
-// // else
-// // #endif
-// // this->flush();
-// // }
-
using File = GZfstream<char>;
-}
-
-
-
+} // namespace iohelper
#endif /* IOHELPER_FILE_MANAGER_H_ */
diff --git a/third-party/iohelper/src/iohelper_common.hh b/third-party/iohelper/src/iohelper_common.hh
index 4c8d117c7..5265a42a9 100644
--- a/third-party/iohelper/src/iohelper_common.hh
+++ b/third-party/iohelper/src/iohelper_common.hh
@@ -1,294 +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 <cstdint>
+#include <cstdlib>
+#include <cstring>
#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_ */

Event Timeline